package com.czg.controller.pay;

import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.czg.PayCst;
import com.czg.annotation.Debounce;
import com.czg.constants.ParamCodeCst;
import com.czg.exception.CzgException;
import com.czg.market.service.OrderInfoService;
import com.czg.order.dto.CheckOrderPay;
import com.czg.order.entity.OrderInfo;
import com.czg.order.service.OrderInfoCustomService;
import com.czg.resp.CzgResult;
import com.czg.service.order.dto.OrderPayParamDTO;
import com.czg.service.order.service.OrderPayService;
import com.czg.system.service.SysParamsService;
import com.czg.utils.AssertUtil;
import com.czg.utils.ServletUtil;
import com.mybatisflex.core.query.QueryWrapper;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;

/**
 * 支付
 *
 * @author ww
 * @description
 */
@RestController
@RequestMapping("/pay")
public class OrderPayController {
    @Resource
    private OrderPayService orderPayService;
    @Resource
    private OrderInfoCustomService orderInfoCustomService;
    @Resource
    private OrderInfoService orderInfoService;
    @DubboReference
    private SysParamsService paramsService;
    @Value("${spring.profiles.active}")
    private String env;

    @PostMapping("/creditPay")
    @Debounce(value = "#payParam.checkOrderPay.orderId")
    public CzgResult<Object> creditPayOrder(@RequestHeader Long shopId, @Validated @RequestBody OrderPayParamDTO payParam) {
        payParam.setShopId(shopId);
        return orderPayService.creditPayOrder(payParam);
    }

    @PostMapping("/cashPay")
    @Debounce(value = "#payParam.checkOrderPay.orderId")
    public CzgResult<Object> cashPayOrder(@RequestHeader Long shopId, @Validated @RequestBody OrderPayParamDTO payParam) {
        payParam.setShopId(shopId);
        return orderPayService.cashPayOrder(payParam);
    }

    /**
     * 充值并付款
     * payType 必填  支付方式，ALIPAY 支付宝，WECHAT 微信
     * openId  必填
     */
    @PostMapping("/rechargePayOrder")
    @Debounce(value = "#payParam.checkOrderPay.orderId")
    public CzgResult<Map<String, Object>> rechargePayOrder(@RequestHeader Long shopId, HttpServletRequest request, @Validated @RequestBody OrderPayParamDTO payParam) {
        payParam.setShopId(shopId);
        return orderPayService.rechargePayOrder(ServletUtil.getClientIP(request), payParam);
    }

    /**
     * 会员支付
     * payType 必填
     * <p>
     * scanCode(收银机使用) 会员码支付 authCode 必填
     * userPay(收银机使用) 选择用户支付 userId必填
     * <p>
     * accountPay(小程序使用) 密码支付 用户密码pwd 必填
     */
    @PostMapping("/vipPay")
    @Debounce(value = "#payParam.checkOrderPay.orderId")
    public CzgResult<Object> vipPayOrder(@RequestHeader Long shopId, @Validated @RequestBody OrderPayParamDTO payParam) {
        payParam.setShopId(shopId);
        AssertUtil.isBlank(payParam.getPayType(), "支付类型不可为空");
        return orderPayService.vipPayOrder(payParam);
    }

    /**
     * h5支付
     */
    @PostMapping("/h5Pay")
    @Debounce(value = "#payParam.checkOrderPay.orderId")
    public CzgResult<Map<String, Object>> h5PayOrder(@RequestHeader Long shopId, HttpServletRequest request, @Validated @RequestBody OrderPayParamDTO payParam) {
        payParam.setShopId(shopId);
        return orderPayService.h5PayOrder(ServletUtil.getClientIP(request, ""), payParam);
    }

    /**
     * js支付
     * <p>
     * payType 必填  支付方式，ALIPAY 支付宝，WECHAT 微信
     * openId  必填
     */
    @PostMapping("/jsPay")
    @Debounce(value = "#payParam.checkOrderPay.orderId")
    public CzgResult<Map<String, Object>> jsPayOrder(@RequestHeader Long shopId, HttpServletRequest request, @Validated @RequestBody OrderPayParamDTO payParam) {
        payParam.setShopId(shopId);
        return orderPayService.jsPayOrder(ServletUtil.getClientIP(request), payParam);
    }

    /**
     * 小程序支付
     * payType 必填  支付方式，ALIPAY 支付宝，WECHAT 微信
     * openId  必填
     */
    @PostMapping("/ltPayOrder")
    @Debounce(value = "#payParam.checkOrderPay.orderId")
    public CzgResult<Map<String, Object>> ltPayOrder(@RequestHeader Long shopId, HttpServletRequest request, @Validated @RequestBody OrderPayParamDTO payParam) {
        payParam.setShopId(shopId);
        return orderPayService.ltPayOrder(ServletUtil.getClientIP(request), payParam);
    }

//    /**
//     * 正扫
//     */
//    @PostMapping("/scanPay")
//    @Debounce(value = "#payParam.checkOrderPay.orderId")
//    public CzgResult<Map<String, Object>> scanPayOrder(@RequestHeader Long shopId, HttpServletRequest request, @Validated @RequestBody OrderPayParamDTO payParam) {
//        payParam.setShopId(shopId);
//        return orderPayService.scanPayOrder(ServletUtil.getClientIP(request), payParam);
//    }

    /**
     * 扫码收款
     * authCode 必填 扫描码
     */
    @PostMapping("/microPay")
    @Debounce(value = "#payParam.checkOrderPay.orderId")
    public CzgResult<Map<String, Object>> microPayOrder(@RequestHeader Long shopId, @Validated @RequestBody OrderPayParamDTO payParam) {
        payParam.setShopId(shopId);
        return orderPayService.microPayOrder(payParam);
    }

    /**
     * 获取店铺订单支付URL
     */
    @PostMapping("/shopPayApi/orderPayUrl")
    @Debounce(value = "#checkOrderPay.orderId")
    public CzgResult<String> getOrderPayUrl(@RequestHeader Long shopId,
                                            @RequestBody CheckOrderPay checkOrderPay) {
        AssertUtil.isNull(shopId, "店铺id不能为空");
        AssertUtil.isNull(checkOrderPay, "订单信息不能为空");
        Map<String, Object> map = new HashMap<>();
        map.put("env", env);
        map.put("shopId", shopId);
        map.put("orderId", checkOrderPay.getOrderId());
        map.put("payAmount", checkOrderPay.getOrderAmount());
        map.put("extend", StrUtil.isEmpty(checkOrderPay.getExtend()) ? "" : checkOrderPay.getExtend());
        if (checkOrderPay.getOrderId() != null) {
            OrderInfo orderInfo = orderInfoCustomService.checkOrderPay(checkOrderPay);
            map.put("payAmount", orderInfo.getOrderAmount());
        }
        String baseUrl = paramsService.getSysParamValue(ParamCodeCst.System.SHOP_ORDER_PAY_BASE_URL);
        String buildUrl = URLUtil.buildQuery(map, Charset.defaultCharset());
        String fullUrl = baseUrl.concat("?").concat(buildUrl);
        return CzgResult.success(fullUrl);
    }

    /**
     * 空订单支付/h5页面支付
     * payType 必填  支付方式，ALIPAY 支付宝，WECHAT 微信
     * openId  必填
     * checkOrderPay.orderAmount 必填
     */
    @PostMapping("/shopPayApi/js2Pay")
    @Debounce(value = "#payParam.checkOrderPay.orderId")
    public CzgResult<Map<String, Object>> js2PayOrder(HttpServletRequest request, @RequestBody OrderPayParamDTO payParam) {
        if ("ALIPAY".equals(payParam.getPayType())) {
            payParam.setPayType(PayCst.Type.ALIPAY);
        } else if ("WECHAT".equals(payParam.getPayType())) {
            payParam.setPayType(PayCst.Type.WECHAT);
        } else {
            throw new CzgException(payParam.getPayType() + "支付方式错误");
        }
        return orderPayService.js2PayOrder(ServletUtil.getClientIP(request), payParam);
    }

    /**
     * 获取订单状态
     * unpaid-待支付;in-production 制作中;wait_out 待取餐;;done-订单完成;refunding-申请退单;refund-退单;part_refund 部分退单;cancelled-取消订单
     */
    @GetMapping("/queryOrderStatus")
    public CzgResult<String> queryOrderStatus(Long orderId) {
        CzgResult<String> result = CzgResult.success();
        String status = orderInfoService.getOneAs(QueryWrapper.create().select(OrderInfo::getStatus).eq(OrderInfo::getId, orderId), String.class);
        result.setData(status);
        switch (status) {
            case "unpaid" -> result.setMsg("等待用户付款");
            case "done" -> result.setMsg("支付完成");
            case "cancelled" -> result.setMsg("订单已取消");
        }
        return result;
    }
}
