package com.example.his.api.front.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.felord.payment.wechat.v3.WechatApiProvider;
import cn.felord.payment.wechat.v3.model.ResponseSignVerifyParams;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import cn.hutool.json.JSONObject;
import com.example.his.api.common.result.R;
import com.example.his.api.config.sa_token.StpCustomerUtil;
import com.example.his.api.front.service.OrderService;
import com.example.his.api.req.FrontOrder.CreatePaymentForm;
import com.example.his.api.req.FrontOrder.RefundForm;
import com.example.his.api.req.FrontOrder.SearchOrderByPageForm;
import com.example.his.api.req.FrontOrder.SearchPaymentResultForm;
import com.example.his.api.socket.WebSocketService;
import com.github.pagehelper.PageInfo;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

@RestController("FrontOrderController")
@RequestMapping("/front/order")
@Slf4j
public class OrderController {

    @Resource
    private OrderService orderService;

    @Resource
    private WechatApiProvider wechatApiProvider;
    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    /**
     * 创建付款单
     * @param form
     * @return
     */
    @PostMapping("/createPayment")
    @SaCheckLogin(type = StpCustomerUtil.TYPE)
    public R createPayment(@Valid @RequestBody CreatePaymentForm form) {
        int customerId = StpCustomerUtil.getLoginIdAsInt();
        Map param = BeanUtil.beanToMap(form);
        param.put("customerId",customerId);
        HashMap map = orderService.createPayment(param);

//        HashMap resultMap = new HashMap();
        if(map == null){
            return R.success(new HashMap() {{
                put("illegal", true);
            }});
        }else {
            map.put("illegal", false);
            return R.success(map);
        }

    }

    /**
     * 付款结果通知
     * @param serial
     * @param signature
     * @param timestamp
     * @param nonce
     * @param request
     * @return
     */
    @SneakyThrows
    @PostMapping("/paymentCallback")
    public Map paymentCallback(
            @RequestHeader("Wechatpay-Serial") String serial,
            @RequestHeader("Wechatpay-Signature") String signature,
            @RequestHeader("Wechatpay-Timestamp") String timestamp,
            @RequestHeader("Wechatpay-Nonce") String nonce,
            HttpServletRequest request) {
        String body = request.getReader().lines().collect(Collectors.joining());
        // 对请求头进行验签 以确保是微信服务器的调用
        ResponseSignVerifyParams params = new ResponseSignVerifyParams();
        params.setWechatpaySerial(serial);
        params.setWechatpaySignature(signature);
        params.setWechatpayTimestamp(timestamp);
        params.setWechatpayNonce(nonce);
        params.setBody(body);
        return wechatApiProvider.callback("his-vue").transactionCallback(params, data -> {
            String transactionId = data.getTransactionId();
            String outTradeNo = data.getOutTradeNo();
            //更新订单状态和付款单ID
            HashMap map = new HashMap();
            map.put("transactionId", transactionId);
            map.put("outTradeNo", outTradeNo);
            boolean bool = orderService.updatePayment(map);
            // 用WebSocket通知前端项目付款成功
            //这里是新添加的代码
            if (bool) {
                log.debug("订单付款成功，已更新订单状态");
                //查询订单的customerId
                Integer customerId = orderService.searchCustomerId(outTradeNo);
                if (customerId == null) {
                    log.error("没有查询到customerId");
                } else {
                    //推送消息给前端页面
                    JSONObject json = new JSONObject();
                    json.set("result", true);
                    WebSocketService.sendInfo(json.toString(), "customer_" + outTradeNo);
                }
            } else {
                log.error("订单付款成功，但是状态更新失败");
            }
        });
    }


    /**
     * 查询付款结果
     * @param form
     * @return
     */
    @PostMapping("/searchPaymentResult")
    @SaCheckLogin(type = StpCustomerUtil.TYPE)
    public R searchPaymentResult(@Valid @RequestBody SearchPaymentResultForm form) {
        boolean bool = orderService.searchPaymentResult(form.getOutTradeNo());
        return R.success(bool);
    }

    /**
     * 查询订单记录
     * @param form
     * @return
     */
    @PostMapping("/searchFrontOrderByPage")
    public R searchFrontOrderByPage(@Valid @RequestBody SearchOrderByPageForm form) {
        int customerId = StpCustomerUtil.getLoginIdAsInt();
        Map param = BeanUtil.beanToMap(form);
        param.put("customerId",customerId);
        PageInfo<HashMap> list = orderService.searchFrontOrderByPage(param);
        return R.success(list);
    }

    /**
     * 申请退款
     * @param form
     * @return
     */
    @PostMapping("/applyRefund")
    @SaCheckLogin(type = StpCustomerUtil.TYPE)
    public R applyRefund(@RequestBody @Valid RefundForm form) {
        int customerId = StpCustomerUtil.getLoginIdAsInt();
        form.setCustomerId(customerId);
        Map param = BeanUtil.beanToMap(form);
        boolean bool = orderService.applyRefund(param);
        return R.success(bool);
    }

    /**
     * 退款结果通知
     * @param serial
     * @param signature
     * @param timestamp
     * @param nonce
     * @param request
     * @return
     */
    @SneakyThrows
    @PostMapping("/refundCallback")
    public Map refundCallback(
            @RequestHeader("Wechatpay-Serial") String serial,
            @RequestHeader("Wechatpay-Signature") String signature,
            @RequestHeader("Wechatpay-Timestamp") String timestamp,
            @RequestHeader("Wechatpay-Nonce") String nonce,
            HttpServletRequest request) {
        String body = request.getReader().lines().collect(Collectors.joining());
        //验证数字签名，确保是微信服务器发送的通知消息
        ResponseSignVerifyParams params = new ResponseSignVerifyParams();
        params.setWechatpaySerial(serial);
        params.setWechatpaySignature(signature);
        params.setWechatpayTimestamp(timestamp);
        params.setWechatpayNonce(nonce);
        params.setBody(body);
        return wechatApiProvider.callback("his-vue").refundCallback(params, data -> {
            //判断退款是否成功
            String status = data.getRefundStatus().toString();

            if ("SUCCESS".equals(status)) {
                String outRefundNo = data.getOutRefundNo();
                //把订单更新成已退款状态
                boolean bool = orderService.updateRefundStatus(outRefundNo);
                if (!bool) {
                    log.error("订单状态更新失败");
                } else {
                    log.debug("退款流水号为" + outRefundNo + "的订单退款成功");
                    //推送消息给前端页面
                    JSONObject json = new JSONObject();
                    json.set("result", true);
                    WebSocketService.sendInfo(json.toString(), "customer_" + data.getOutTradeNo());
                }
            } else if ("ABNORMAL".equals(status)) {
                //用户银行卡作废或者冻结，发送短信给用户手机，让用户联系客服执行手动退款到其他银行卡
            }

        });
    }


    /**
     * 获取未付款订单支付二维码
     */
    @GetMapping("/qrCode")
    public R getQrCode(@RequestParam String outTradeNo) {
        int customerId = StpCustomerUtil.getLoginIdAsInt();
        String key = "codeUrl_" + customerId + "_" + outTradeNo;
        if(redisTemplate.hasKey(key)){
            String codeUrl = redisTemplate.opsForValue().get(key).toString();
            QrConfig qrConfig = new QrConfig();
            qrConfig.setWidth(230);
            qrConfig.setHeight(230);
            qrConfig.setMargin(2);
            String qrCodeBase64 = QrCodeUtil.generateAsBase64(codeUrl, qrConfig, "jpg");
            return R.success(qrCodeBase64);
        }else {
            return R.success(false);
        }

    }

    /**
     * 关闭未支付的订单
     */
    @GetMapping("/closeOrderById")
    @SaCheckLogin(type = StpCustomerUtil.TYPE)
    public R closeOrderById(@RequestParam Integer id) {
        int customerId = StpCustomerUtil.getLoginIdAsInt();
        HashMap param = new HashMap();
        param.put("customerId", customerId);
        param.put("id", id);
        boolean bool = orderService.closeOrderById(param);
        return R.success(bool);
    }


}
