package org.dromara.system.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.dtflys.forest.annotation.Body;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.service.WxPayService;
import cn.binarywang.wx.miniapp.api.WxMaQrcodeService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaCodeLineColor;
import io.undertow.servlet.spec.HttpServletRequestImpl;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.io.IOUtils;
import org.dromara.common.core.domain.R;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.web.core.BaseController;
import org.dromara.system.domain.bo.TblDzbcBannerBo;
import org.dromara.system.domain.bo.TblDzbcOrderBo;
import org.dromara.system.domain.bo.TblDzbcStatisticsBo;
import org.dromara.system.domain.vo.TblDzbcOrderVo;
import org.dromara.system.service.ITblDzbcBannerService;
import org.dromara.system.service.ITblDzbcOrderService;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.Deque;

import java.util.Map;

import org.dromara.system.domain.bo.TblDzbcCargoOrderBo;
import org.dromara.system.domain.vo.TblDzbcCargoOrderVo;
import org.dromara.system.service.ITblDzbcCargoOrderService;

@Validated
@RequiredArgsConstructor
@RestController
@SaIgnore
@Slf4j
@RequestMapping("/system/commonOther")
public class CommonDzbcOtherController extends BaseController {

    private final ITblDzbcBannerService bannerService;

    private final ITblDzbcOrderService orderService;
    private final ITblDzbcCargoOrderService cargoOrderService;
    private final WxPayService wxPayService;
    private final WxMaService wxMaService;





    /**
     * 小程序banner列表
     */
    @GetMapping("/list")
    public R<Object> list(TblDzbcBannerBo bo) {
        return R.ok(bannerService.queryList(bo));
    }

    @ResponseBody
    @Log(title = "定制班车-订单微信支付回调", businessType = BusinessType.UPDATE)
    @RequestMapping("/wx")
    public String payNotify(HttpServletRequest request, HttpServletResponse response) {
        try {
            String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
            WxPayOrderNotifyResult result = wxPayService.parseOrderNotifyResult(xmlResult);

            String outTradeNo = result.getOutTradeNo();

            // ==================== 1. 货物订单处理 (前缀 "C") ====================
            if (outTradeNo != null && outTradeNo.startsWith("C")) {
                // 校验业务结果是否成功
                if (!"SUCCESS".equals(result.getResultCode())) {
                    log.error("货物订单支付回调业务失败: {}", result.getErrCodeDes());
                    return WxPayNotifyResponse.fail(result.getErrCodeDes());
                }

                try {
                    String orderIdStr = outTradeNo.substring(1); // 去掉 "C"
                    Long orderId = Long.parseLong(orderIdStr);

                    TblDzbcCargoOrderVo order = cargoOrderService.queryById(orderId);
                    if (order != null && order.getPayStatus() == 0) {
                        TblDzbcCargoOrderBo updateBo = new TblDzbcCargoOrderBo();
                        updateBo.setId(orderId);
                        updateBo.setPayStatus(1); // 1-已支付

                        // 补充支付信息
                        updateBo.setPayTradeNo(result.getTransactionId());
                        if (result.getTimeEnd() != null) {
                            try {
                                updateBo.setPayTime(cn.hutool.core.date.DateUtil.parse(result.getTimeEnd(), "yyyyMMddHHmmss").toLocalDateTime());
                            } catch (Exception e) {
                                updateBo.setPayTime(java.time.LocalDateTime.now());
                            }
                        } else {
                            updateBo.setPayTime(java.time.LocalDateTime.now());
                        }

                        // 状态逻辑：已支付依然是待发货(0)，无需变更status
                        cargoOrderService.updateByBo(updateBo);
                        log.info("货物订单支付成功处理完成: orderId={}", orderId);
                    }
                } catch (Exception e) {
                    log.error("货物订单支付回调处理异常", e);
                }
                return WxPayNotifyResponse.success("处理成功!");
            }

            // ==================== 2. 定制班车(乘客)订单处理 ====================
            // 加入自己处理订单的业务逻辑，需要判断订单是否已经支付过，否则可能会重复调用
            String orderId = result.getOutTradeNo();
            // String tradeNo = result.getTransactionId(); // 原代码未使用

            try {
                TblDzbcOrderVo order = orderService.queryById(Long.parseLong(orderId));
                if (order.getStatus().equals("0")) {
                    TblDzbcOrderBo order1 = new TblDzbcOrderBo();
                    order1.setId(order.getId());
                    String data = order.getExt2();
                    JSONObject jo = JSONUtil.parseObj(data);
                    jo.put("wxpay", result);
                    order1.setStatus("1");
                    order1.setExt2(JSONUtil.toJsonStr(jo));
                    orderService.updateByBo(order1);
                }
            } catch (Exception e) {
                // 原代码吞掉了异常，保持一致
            }

            // String totalFee = BaseWxPayResult.fenToYuan(result.getTotalFee());
            return WxPayNotifyResponse.success("处理成功!");
        } catch (Exception e) {
            log.error("微信回调结果异常,异常原因{}", e.getMessage());
            return WxPayNotifyResponse.fail(e.getMessage());
        }
    }

    /**
     * 生成二维码
     * @param content 内容
     * @param width 宽度
     * @param height 高度
     */
    @SaIgnore
    @GetMapping("/qrcode")
    public void qrcode(String content, HttpServletResponse response,
                       @RequestParam(defaultValue = "300") int width,
                       @RequestParam(defaultValue = "300") int height) throws IOException {
        response.setContentType("image/png");
        QrCodeUtil.generate(content, width, height, "png", response.getOutputStream());
    }

    /**
     * 生成小程序码（无限制）
     * @param scene 场景值，最多32个可见字符
     * @param page 页面路径，必须是已经发布的小程序存在的页面
     * @param checkPath 检查page是否存在，默认true
     * @param envVersion 环境版本：release正式版, trial体验版, develop开发版，默认release
     * @param width 小程序码宽度，默认430
     * @param autoColor 自动配置线条颜色，默认true
     * @param isHyaline 是否需要透明底色，默认false
     * @param appid 小程序appid，默认使用第一个配置的小程序
     * @param response HttpServletResponse
     */
    @GetMapping("/wxma/qrcode/unlimited")
    public void getUnlimitedQRCode(
            @RequestParam String scene,
            @RequestParam(defaultValue = "") String page,
            @RequestParam(defaultValue = "true") boolean checkPath,
            @RequestParam(defaultValue = "release") String envVersion,
            @RequestParam(defaultValue = "430") int width,
            @RequestParam(defaultValue = "true") boolean autoColor,
            @RequestParam(defaultValue = "false") boolean isHyaline,
            @RequestParam(defaultValue = "wx5c9baacf2aab55b8") String appid,
            HttpServletResponse response) {
        try {
            // 切换到指定小程序
            wxMaService.switchover(appid);
            WxMaQrcodeService qrcodeService = wxMaService.getQrcodeService();

            // 生成小程序码
            // 参数顺序: scene, page, checkPath, envVersion, width, autoColor, lineColor, isHyaline
            byte[] qrCodeBytes = qrcodeService.createWxaCodeUnlimitBytes(scene, page, checkPath, envVersion, width, autoColor, null, isHyaline);

            // 返回图片
            response.setContentType(MediaType.IMAGE_PNG_VALUE);
            response.getOutputStream().write(qrCodeBytes);
            response.getOutputStream().flush();
        } catch (WxErrorException e) {
            log.error("生成小程序码失败: {}", e.getMessage());
            throw new RuntimeException("生成小程序码失败: " + e.getMessage());
        } catch (IOException e) {
            log.error("输出小程序码失败: {}", e.getMessage());
            throw new RuntimeException("输出小程序码失败: " + e.getMessage());
        }
    }


    @ResponseBody
    @Log(title = "定制班车-订单微信退款回调", businessType = BusinessType.UPDATE)
    @RequestMapping("/wx/ref")
    public String payNotifyRef(HttpServletRequest request, HttpServletResponse response) {
        try {
            String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
            WxPayRefundNotifyResult result = wxPayService.parseRefundNotifyResult(xmlResult);

            if (result.getReqInfo() != null) { // 原代码判断 appid!=null，实际上 reqInfo 解密后才关键
                String outTradeNo = result.getReqInfo().getOutTradeNo();

                // ==================== 1. 货物订单退款处理 (前缀 "C") ====================
                if (outTradeNo != null && outTradeNo.startsWith("C")) {
                    try {
                        String orderIdStr = outTradeNo.substring(1);
                        Long orderId = Long.parseLong(orderIdStr);

                        TblDzbcCargoOrderVo order = cargoOrderService.queryById(orderId);
                        if (order != null) {
                            // 收到退款成功回调，更新订单状态
                            TblDzbcCargoOrderBo updateBo = new TblDzbcCargoOrderBo();
                            updateBo.setId(orderId);
                            updateBo.setStatus(4); // 已取消
                            cargoOrderService.updateByBo(updateBo);
                            log.info("货物订单退款成功回调处理完成: orderId={}", orderId);
                        }
                    } catch (Exception e) {
                        log.error("货物订单退款回调处理异常", e);
                    }
                    return WxPayNotifyResponse.success("处理成功!");
                }

                // ==================== 2. 定制班车(乘客)订单退款处理 ====================
                try {
                    TblDzbcOrderVo order = orderService.queryById(Long.parseLong(outTradeNo));
                    if (order.getStatus().equals("2")) {
                        TblDzbcOrderBo order1 = new TblDzbcOrderBo();
                        order1.setId(order.getId());
                        order1.setStatus("4");
                        orderService.updateByBo(order1);

                        order1 = new TblDzbcOrderBo();
                        order1.setId(order.getId());
                        order1.setStatus("5");
                        orderService.updateByBo(order1);
                    }
                } catch (Exception e) {
                    // 原代码吞掉了异常
                }
            }

            // String totalFee = BaseWxPayResult.fenToYuan(result.getTotalFee());
            return WxPayNotifyResponse.success("处理成功!");
        } catch (Exception e) {
            log.error("微信回调结果异常,异常原因{}", e.getMessage());
            return WxPayNotifyResponse.fail(e.getMessage());
        }
    }

    @ResponseBody
    @Log(title = "定制班车-统计", businessType = BusinessType.UPDATE)
    @RequestMapping("/static")
    public R StaticAll(TblDzbcStatisticsBo bo) {
        if(bo==null || bo.getKey()==null) return R.fail("参数存在问题");
        String key = bo.getKey();
        if(key.equals("order")){
           try {
               TblDzbcOrderBo bo1 = JSONUtil.toBean(JSONUtil.toJsonStr(bo.getProps()),TblDzbcOrderBo.class );
               bo1.setParams(bo.getParams());
               return R.ok(orderService.queryListByGroup(bo1));
           }catch (Exception e){
               return R.fail("参数存在问题");
           }

        }
        return R.ok();
    }


}
