package com.hzs.third.pay.controller.api;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.huifu.bspay.sdk.opps.client.BasePayClient;
import com.huifu.bspay.sdk.opps.core.request.*;
import com.huifu.bspay.sdk.opps.core.utils.DateTools;
import com.hzs.common.core.annotation.RepeatSubmitSimple;
import com.hzs.common.core.enums.*;
import com.hzs.common.core.utils.DateUtils;
import com.hzs.common.core.utils.StringUtils;
import com.hzs.common.core.web.domain.AjaxResult;
import com.hzs.common.domain.third.pay.TOnlinePayment;
import com.hzs.third.pay.config.HuiFuConfig;
import com.hzs.third.pay.constants.HuiFuPayConstants;
import com.hzs.third.pay.constants.PayRedisConstants;
import com.hzs.third.pay.controller.base.PayBaseController;
import com.hzs.third.pay.dto.WeChatAppletDTO;
import com.hzs.third.pay.dto.WechatPublicDTO;
import com.hzs.third.pay.dto.WechatStateDTO;
import com.hzs.third.pay.param.WechatCodeParam;
import com.hzs.third.pay.service.ITOnlineCardService;
import com.hzs.third.pay.service.ITOnlinePaymentService;
import com.hzs.third.pay.util.PayUtil;
import com.hzs.third.pay.util.WeChatUtil;
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.validation.Valid;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description: 汇付新支付控制器
 * @Author: jiang chao
 * @Time: 2024/12/5 15:28
 * @Classname: HuiFuPayController
 * @PackageName: com.hzs.third.pay.controller.api
 */
@Slf4j
@RestController
@RequestMapping("/huifu")
public class HuiFuPayController extends PayBaseController {

    @Autowired
    private HuiFuConfig huiFuConfig;
    @Autowired
    private ITOnlinePaymentService itOnlinePaymentService;
    @Autowired
    private ITOnlineCardService itOnlineCardService;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 汇付下单
     *
     * @param param
     * @return
     */
    @RepeatSubmitSimple
    @PostMapping("/code-order")
    public AjaxResult codeOrder(@Valid @RequestBody WechatCodeParam param) {
        try {
            // 是否微信小程序
            boolean appletFlag = false;
            // 用户授权的 openId
            String openId;

            if (null != param.getAppletFlag() && EYesNo.YES.getIntValue() == param.getAppletFlag()) {
                // H5浏览器，需要拉起小程序
                // 微信请求参数
                Map<String, Object> requestParam = new HashMap<>();
                requestParam.put("appid", huiFuConfig.getAppletAppId());
                requestParam.put("secret", huiFuConfig.getAppletAppSecret());
                requestParam.put("js_code", param.getCode());
                requestParam.put("grant_type", "authorization_code");

                // 根据code调用微信 auth.code2Session 接口，获取用户 openId 和 unionId
                String resultStr = HttpUtil.get("https://api.weixin.qq.com/sns/jscode2session", requestParam);
                if (StringUtils.isEmpty(resultStr)) {
                    return AjaxResult.error("请求微信小程序授权异常");
                }
                log.info("请求微信小程序授权返回，resultStr: {}", resultStr);

                // 微信返回json转操作对象
                WeChatAppletDTO weChatAppletDTO = JSONUtil.parseObj(resultStr).toBean(WeChatAppletDTO.class);
                // 判断返回内容是否成功
                String errorMsg = WeChatUtil.handErrorCode(weChatAppletDTO.getErrcode());
                if (StringUtils.isNotEmpty(errorMsg)) {
                    return AjaxResult.error(errorMsg);
                }
                // 用户小程序授权的 openId
                openId = weChatAppletDTO.getOpenid();
                // 标记微信小程序
                appletFlag = true;
            } else {
                // PC、H5微信内置浏览器，走公众号页面
                // 微信请求参数
                Map<String, Object> requestParam = new HashMap<>();
                requestParam.put("appid", huiFuConfig.getPublicAppId());
                requestParam.put("secret", huiFuConfig.getPublicAppSecret());
                requestParam.put("code", param.getCode());
                requestParam.put("grant_type", "authorization_code");

                // 根据code调用微信 oauth2.access_token 接口，获取用户 openId
                String resultStr = HttpUtil.get("https://api.weixin.qq.com/sns/oauth2/access_token", requestParam);
                if (StringUtils.isEmpty(resultStr)) {
                    return AjaxResult.error("请求微信公众号授权异常");
                }
                log.info("请求微信公众号授权返回，resultStr: {}", resultStr);

                // 微信返回json转操作对象
                WechatPublicDTO wechatPublicDTO = JSONUtil.parseObj(resultStr).toBean(WechatPublicDTO.class);
                // 判断返回内容是否成功
                String errorMsg = WeChatUtil.handErrorCode(wechatPublicDTO.getErrcode());
                if (StringUtils.isNotEmpty(errorMsg)) {
                    return AjaxResult.error(errorMsg);
                }
                // 用户公众号授权的 openId
                openId = wechatPublicDTO.getOpenid();
            }

//            openId = "oFtf56CBcrsKFTXePWZWznYTjH9s";

            log.info("调用汇付新微信扫码支付前置微信授权! order: {}, openId: {}", param.getState(), openId);

            // redis 缓存KEY
            String stateKey = String.format(PayRedisConstants.HUIFU_STATE_KEY, param.getState());
            if (!redisTemplate.hasKey(stateKey)) {
                log.error("新汇付跳转微信支付失败，缓存订单已不存在");
                return AjaxResult.error("支付失败，请重新发起支付.");
            } else {
                Object payInfo = redisTemplate.opsForValue().get(stateKey);
                if (null == payInfo) {
                    log.error("新汇付跳转微信支付失败，缓存订单为空");
                    return AjaxResult.error("支付失败，请重新发起支付.");
                }
                // 缓存的支付信息
                WechatStateDTO wechatStateDTO = JSONUtil.toBean(payInfo.toString(), WechatStateDTO.class);

                // 支付类型
                int businessType = wechatStateDTO.getType();
                // 订单编号
                String orderCode = wechatStateDTO.getOrderCode();
                // 同一订单不能重复，此处添加随机数，防止多次调用
                String thirdOrderCode = PayUtil.getThirdOrderCode(orderCode, null);

                TOnlinePayment tOnlinePayment = itOnlinePaymentService.queryByBusiness(businessType, orderCode, null);
                if (null == tOnlinePayment) {
                    log.error("新汇付跳转微信支付失败，在线支付信息不存在");
                    return AjaxResult.error("支付失败，请重新发起支付!");
                }
                if (EPayStatus.PAID.getValue() == tOnlinePayment.getPayStatus()) {
                    // 在线支付信息已支付
                    log.error("新汇付跳转微信支付失败，在线支付信息已支付");
                    return AjaxResult.error("订单已支付");
                }

                // 实际支付金额（在线支付都需要随机立减）
                BigDecimal amount = PayUtil.handleAmountRandom(tOnlinePayment.getBusinessMoney());

                // 组装交易参数
                V2TradePaymentJspayRequest request = new V2TradePaymentJspayRequest();
                // 请求日期
                request.setReqDate(DateTools.getCurrentDateYYYYMMDD());
                // 请求流水号（保证唯一）
                request.setReqSeqId(thirdOrderCode);
                // 商户id
                request.setHuifuId(huiFuConfig.getSysId());
                // 商品描述
                request.setGoodsDesc("支付：" + tOnlinePayment.getBusinessCode());
                // 交易类型
                if (appletFlag) {
                    // T_MINIAPP：微信小程序
                    request.setTradeType("T_MINIAPP");
                } else {
                    // T_JSAPI：微信公众号支付
                    request.setTradeType("T_JSAPI");
                }
                // 交易金额（单位元）
                request.setTransAmt(new DecimalFormat("#0.00").format(amount.doubleValue()));

                Map<String, Object> extendInfoMap = new HashMap<>();
                // 该笔交易的异步通知地址（http/https异步通知地址，必须以virgo://开头）
                extendInfoMap.put("notify_url", huiFuConfig.getNotifyUrl());
                // 交易有效期（24小时）
                extendInfoMap.put("time_expire", DateTools.dateToDateString(DateUtils.addHours(tOnlinePayment.getModifiedTime(), 24), DateTools.DATE_TIME_YYYYMMDDHHMMSS));
                // 备注（交易后原样返回）
                extendInfoMap.put("remark", tOnlinePayment.getBusinessType().toString());
                // 微信相关信息
                JSONObject wxData = new JSONObject();
                // 交易类型
                if (appletFlag) {
                    // T_MINIAPP：微信小程序
                    wxData.putOpt("sub_appid", huiFuConfig.getAppletAppId());
                } else {
                    // T_JSAPI：微信公众号支付
                    wxData.putOpt("sub_appid", huiFuConfig.getPublicAppId());
                }
                wxData.putOpt("sub_openid", openId);
                extendInfoMap.put("wx_data", wxData);
                // 扩展参数
                request.setExtendInfo(extendInfoMap);

                log.info("新汇付跳转微信支付调用参数：{}", JSONUtil.toJsonStr(request));

                Map<String, Object> response = BasePayClient.request(request);

                log.info("新汇付跳转微信支付调用返回：{}", JSONUtil.toJsonStr(response));

                if (HuiFuPayConstants.TRANS_SUCCESS.equals(response.get("trans_stat").toString())
                        || HuiFuPayConstants.TRANS_PROCESSING.equals(response.get("trans_stat").toString())) {
                    // 返回成功

                    // 更新新汇付全局流水号
                    itOnlinePaymentService.update(Wrappers.<TOnlinePayment>lambdaUpdate()
                            .eq(TOnlinePayment::getPkId, tOnlinePayment.getPkId())
                            .set(TOnlinePayment::getPayNumber, response.get("hf_seq_id").toString())
                    );

                    // 微信支付数据
                    JSONObject payInfoResult = JSONUtil.parseObj(response.get("pay_info"));
                    return AjaxResult.success("", payInfoResult);
                } else {
                    log.error("新汇付跳转微信支付返回失败! resp_desc: {}, bank_message: {}, hf_seq_id: {}", response.get("resp_desc"), response.get("bank_message"), response.get("hf_seq_id"));
                    return AjaxResult.error("支付失败，请刷新后重试!");
                }
            }
        } catch (Exception e) {
            log.error("新汇付跳转微信支付处理返回异常!", e);
            return AjaxResult.error("支付异常，请返回刷新后重试");
        }
    }

//    /**
//     * 快捷绑卡
//     *
//     * @param param
//     * @return
//     */
//    @RepeatSubmitSimple
//    @PostMapping("/bind")
//    public AjaxResult bind(@Valid @RequestBody FastBindParam param) {
//        if ((StringUtils.isNotEmpty(param.getValiddate()) && StringUtils.isEmpty(param.getCvv2()))
//                || (StringUtils.isEmpty(param.getValiddate()) && StringUtils.isNotEmpty(param.getCvv2()))) {
//            return AjaxResult.error("绑定信用卡时，必须要输入【安全码】以及【有效期】");
//        }
//        if (null != param.getValiddate() && param.getValiddate().length() > 4) {
//            return AjaxResult.error("【有效期】不能超过4位");
//        }
//
//        // 银行卡号去空格
//        String bankNo = StringUtils.deleteWhitespace(param.getBankNo());
//        // 返回前端错误信息
//        String errorMsg = "";
//
//        try {
//            // 当前用户
//            Long userId = SecurityUtils.getUserId();
//            // 所属国家
//            Integer pkCountry = SecurityUtils.getPkCountry();
//
//            TOnlineCard checkCard = itOnlineCardService.checkUserBankExist(userId, bankNo, huiFuConfig.getSysId(), pkCountry);
//            if (checkCard != null) {
//                return AjaxResult.error("已经绑定过该卡，不能重复绑定");
//            }
//
//            // 绑卡编号
//            String code = CommonUtil.createSerialNumber(EOrderPrefix.THIRD_CODE);
//            // 绑卡类型
//            int bindType = EBankCardType.DEBIT.getValue();
//
//            // 组装交易参数
//            V3QuickbuckleApplyRequest request = new V3QuickbuckleApplyRequest();
//            // 请求日期
//            request.setReqDate(DateTools.getCurrentDateYYYYMMDD());
//            // 请求流水号（保证唯一）
//            request.setReqSeqId(code);
//            // 商户id
//            request.setHuifuId(huiFuConfig.getSysId());
//            // 商户用户id
//            request.setOutCustId(userId.toString());
//            // 银行卡号
//            request.setCardNo(RsaUtils.encrypt(param.getBankNo(), huiFuConfig.getSelfPublicKey()));
//            // 银行卡开户姓名
//            request.setCardName(RsaUtils.encrypt(param.getName(), huiFuConfig.getSelfPublicKey()));
//            // 银行卡绑定身份证
//            request.setCertNo(RsaUtils.encrypt(param.getIdCard(), huiFuConfig.getSelfPublicKey()));
//            // 银行卡绑定手机号
//            request.setMobileNo(RsaUtils.encrypt(param.getPhone(), huiFuConfig.getSelfPublicKey()));
//            // 证件有效期类型（1=长期有效，0=非长期有效）
//            request.setCertValidityType("1");
//            // 证件有效期起效日
//            request.setCertBeginDate("20250120");
//            // 授权信息（招行必传）
//            request.setProtocolNo("34463343");
//            // 信用卡相关追加信息
//            Map<String, Object> extendInfoMap = new HashMap<>();
//            if (StringUtils.isNotEmpty(param.getCvv2())) {
//                // 信用卡cvv2
//                extendInfoMap.put("cvv2", RsaUtils.encrypt(param.getCvv2(), huiFuConfig.getSelfPublicKey()));
//            }
//            if (StringUtils.isNotEmpty(param.getValiddate())) {
//                // 信用卡有效期
//                extendInfoMap.put("expiration", RsaUtils.encrypt(param.getValiddate(), huiFuConfig.getSelfPublicKey()));
//            }
//            // 扩展参数
//            request.setExtendInfo(extendInfoMap);
//
//            log.info("新汇付跳转支付宝支付调用参数：{}", JSONUtil.toJsonStr(request));
//
//            Map<String, Object> response = BasePayClient.request(request);
//
//            log.info("新汇付跳转支付宝支付调用返回：{}", JSONUtil.toJsonStr(response));
//
//            // 汇付快捷绑卡处理
//            Map<String, Object> params = new HashMap<>();
//            params.put("app_id", adaPayConfig.getAppId());
//            params.put("member_id", memberId);
//            params.put("card_id", bankNo);
//            params.put("tel_no", param.getPhone());
//            if (StringUtils.isNotEmpty(param.getCvv2()) && StringUtils.isNotEmpty(param.getValiddate())) {
//                // 信用卡安全码
//                params.put("vip_code", param.getCvv2());
//                // 信用卡有效期
//                params.put("expiration", param.getValiddate());
//                // 贷记卡（信用卡）
//                bindType = EBankCardType.CREDIT.getValue();
//            }
//            // 招行借记卡绑卡
//            params.put("protocol_no", "34463343");
//
//            log.info("汇付快捷绑卡请求参数：{}", params);
//
//            Map<String, Object> resultMap = FastPay.cardApply(params, adaPayConfig.getAppId());
//
//            log.info("汇付快捷绑卡返回参数： {}", resultMap);
//
//            if (AdaPayConstants.SUCCESS.equals(resultMap.get("status").toString())) {
//                // 返回成功
//
//                // 插入银行卡明细表
//                TOnlineCard tOnlineCard = new TOnlineCard();
//                tOnlineCard.setCode(code);
//                tOnlineCard.setName(param.getName());
//                tOnlineCard.setIdCard(param.getIdCard());
//                tOnlineCard.setBankNo(bankNo);
//                tOnlineCard.setPhone(param.getPhone());
//                tOnlineCard.setBindId(resultMap.get("id").toString());
//                tOnlineCard.setCustomerNum(adaPayConfig.getAppId());
//                tOnlineCard.setValiddate(param.getValiddate());
//                tOnlineCard.setCvv2(param.getCvv2());
//                tOnlineCard.setBindType(bindType);
//                tOnlineCard.setPkCreator(userId);
//                tOnlineCard.setPkCountry(pkCountry);
//                if (itOnlineCardService.save(tOnlineCard)) {
//                    return AjaxResult.success("", code);
//                } else {
//                    errorMsg = "绑卡保存失败";
//                    log.error("汇付快捷绑卡入库失败");
//                }
//            } else {
//                errorMsg = resultMap.get("error_msg").toString();
//                log.error("汇付快捷绑卡返回失败! code: {}, msg: {}, invalid_param: {}", resultMap.get("error_code"), resultMap.get("error_msg"), resultMap.get("invalid_param"));
//            }
//        } catch (Exception e) {
//            errorMsg = "绑卡处理异常";
//            log.error("调用汇付快捷绑卡处理异常!", e);
//        }
//        return AjaxResult.error("操作失败：" + errorMsg);
//    }


}
