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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.huifu.adapay.model.AdapayCommon;
import com.huifu.adapay.model.FastPay;
import com.huifu.adapay.model.Member;
import com.hzs.common.core.annotation.RepeatSubmitSimple;
import com.hzs.common.core.config.BdConfig;
import com.hzs.common.core.constant.msg.CommonMsgConstants;
import com.hzs.common.core.enums.*;
import com.hzs.common.core.utils.CommonUtil;
import com.hzs.common.core.utils.StringUtils;
import com.hzs.common.core.web.domain.AjaxResult;
import com.hzs.common.domain.third.pay.TOnlineCard;
import com.hzs.common.domain.third.pay.TOnlinePayment;
import com.hzs.common.domain.third.pay.TOnlineThirdBind;
import com.hzs.common.security.utils.SecurityUtils;
import com.hzs.common.util.TransactionUtils;
import com.hzs.third.pay.config.AdaPayConfig;
import com.hzs.third.pay.constants.AdaPayConstants;
import com.hzs.third.pay.controller.base.PayBaseController;
import com.hzs.third.pay.param.FastBindConfirmParam;
import com.hzs.third.pay.param.FastBindParam;
import com.hzs.third.pay.param.FastPayOrderParam;
import com.hzs.third.pay.param.FastUnBindParam;
import com.hzs.third.pay.service.ITOnlineCardService;
import com.hzs.third.pay.service.ITOnlinePaymentService;
import com.hzs.third.pay.service.ITOnlineThirdBindService;
import com.hzs.third.pay.vo.BindCardVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 汇付快捷支付控制器
 */
@Slf4j
@RestController
@RequestMapping("/ada-fast")
public class AdaPayFastController extends PayBaseController {

    @Autowired
    private AdaPayConfig adaPayConfig;
    @Autowired
    private ITOnlineCardService itOnlineCardService;
    @Autowired
    private ITOnlineThirdBindService itOnlineThirdBindService;
    @Autowired
    private ITOnlinePaymentService itOnlinePaymentService;

    /**
     * 绑卡列表
     *
     * @return
     */
    @GetMapping("/list")
    public AjaxResult list() {
        List<BindCardVO> resultList = new ArrayList<>();

        List<TOnlineCard> tOnlineCardList = itOnlineCardService.queryBankList(SecurityUtils.getUserId(), adaPayConfig.getAppId(), SecurityUtils.getPkCountry());
        for (TOnlineCard tOnlineCard : tOnlineCardList) {
            resultList.add(BindCardVO.builder()
                    .bindCode(tOnlineCard.getCode())
                    // 银行卡只显示后4位
                    .bankNo(tOnlineCard.getBankNo().substring(tOnlineCard.getBankNo().length() - 4))
                    .bankName(tOnlineCard.getBankName())
                    .build());
        }
        return AjaxResult.success(resultList);
    }

    /**
     * 快捷绑卡
     *
     * @param param
     * @return
     */
    @RepeatSubmitSimple
    @PostMapping("/bind")
    public AjaxResult bind(@RequestBody FastBindParam param) {
        if (StringUtils.isAnyEmpty(param.getName(), param.getIdCard(), param.getBankNo(), param.getPhone())) {
            return AjaxResult.error("缺少参数");
        }
        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, adaPayConfig.getAppId(), SecurityUtils.getPkCountry());
            if (checkCard != null) {
                return AjaxResult.error("已经绑定过该卡，不能重复绑定");
            }

            // 绑卡编号
            String code = CommonUtil.createSerialNumber(EOrderPrefix.THIRD_CODE);
            // 用户对应的唯一ID
            String memberId;

            QueryWrapper<TOnlineThirdBind> bindQueryWrapper = new QueryWrapper<>();
            bindQueryWrapper.eq("PK_MEMBER", userId);
            bindQueryWrapper.eq("CHANNEL", EPayChannel.ADAPAY.getValue());
            bindQueryWrapper.eq("TYPE", EThirdBindType.PAY_MEMBER.getValue());
            bindQueryWrapper.eq("USER_OTHER", param.getName());
            TOnlineThirdBind tOnlineThirdBind = itOnlineThirdBindService.getOne(bindQueryWrapper);
            if (null == tOnlineThirdBind) {
                // 如果第一次，需要注册并添加绑定数据
                memberId = UUID.randomUUID().toString();
                if (EEnv.TEST.getValue().equals(BdConfig.getEnv())) {
                    // 如果是测试环境
                    memberId = memberId + "-t";
                }
                // 只能为英文、数字或者下划线的一种或多种组合（此处需要替换 - 为 _）
                memberId = memberId.replaceAll("-", "_");

                // 汇付创建用户处理
                Map<String, Object> memberParams = new HashMap<>();
                memberParams.put("app_id", adaPayConfig.getAppId());
                memberParams.put("member_id", memberId);
                memberParams.put("tel_no", param.getPhone());
                memberParams.put("user_name", param.getName());
                // 目前只支付身份证校验
                memberParams.put("cert_type", "00");
                memberParams.put("cert_id", param.getIdCard());

                log.info("汇付快捷绑卡创建用户请求参数：{}", memberParams);

                Map<String, Object> memberResultMap = Member.create(memberParams, adaPayConfig.getAppId());

                log.info("汇付快捷绑卡创建用户返回参数： {}", memberResultMap);

                if (!AdaPayConstants.SUCCESS.equals(memberResultMap.get("status").toString())) {
                    // 返回失败
                    log.error("汇付快捷绑卡创建用户返回失败! code: {}, msg: {}, invalid_param: {}", memberResultMap.get("error_code"), memberResultMap.get("error_msg"), memberResultMap.get("invalid_param"));
                    return AjaxResult.error(TransactionUtils.getContent(CommonMsgConstants.OPERATION_FAILED_FLUSH));
                }

                tOnlineThirdBind = new TOnlineThirdBind();
                tOnlineThirdBind.setPkMember(userId);
                tOnlineThirdBind.setUserOther(param.getName());
                tOnlineThirdBind.setChannel(EPayChannel.ADAPAY.getValue());
                tOnlineThirdBind.setType(EThirdBindType.PAY_MEMBER.getValue());
                tOnlineThirdBind.setBindInfo(memberId);
                itOnlineThirdBindService.save(tOnlineThirdBind);
            } else {
                // 如果已经绑定，则直接使用
                memberId = tOnlineThirdBind.getBindInfo();
            }

            // 绑卡类型
            int bindType = EBankCardType.DEBIT.getValue();

            // 汇付快捷绑卡处理
            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);
    }

    /**
     * 确认绑卡
     *
     * @param param
     * @return
     */
    @RepeatSubmitSimple
    @PostMapping("/bind-confirm")
    public AjaxResult bindConfirm(@RequestBody FastBindConfirmParam param) {
        if (StringUtils.isAnyEmpty(param.getBindCode(), param.getSmsCode())) {
            return AjaxResult.error("缺少参数");
        }

        try {
            // 当前用户
            Long userId = SecurityUtils.getUserId();

            TOnlineCard tOnlineCard = itOnlineCardService.queryCardByCode(param.getBindCode(), userId, adaPayConfig.getAppId(), SecurityUtils.getPkCountry());
            if (null == tOnlineCard) {
                return AjaxResult.error("用户未绑定该银行卡");
            }

            if (EBindStatus.BIND.getValue() == tOnlineCard.getBindStatus()) {
                // 如果已经绑定成功，则直接返回
                return AjaxResult.success();
            }

            Map<String, Object> params = new HashMap<>();
            params.put("apply_id", tOnlineCard.getBindId());
            params.put("sms_code", param.getSmsCode());
            params.put("notify_url", adaPayConfig.getFastCallBackUrl());

            log.info("汇付绑卡确认请求参数： {}", params);

            Map<String, Object> resultMap = FastPay.cardConfirm(params, adaPayConfig.getAppId());

            log.info("汇付绑卡确认返回参数： {}", resultMap);

            if (AdaPayConstants.SUCCESS.equals(resultMap.get("status").toString())) {
                // 返回成功

                // 更新银行卡明细表
                tOnlineCard.setBindStatus(EBindStatus.BIND.getValue());
                tOnlineCard.setBankName(resultMap.get("bank_name").toString());
                tOnlineCard.setThirdInfo(resultMap.get("token_no").toString());
                tOnlineCard.setPkModified(userId);
                tOnlineCard.setModifiedTime(new Date());
                if (itOnlineCardService.updateBankInfo(tOnlineCard) > 0) {
                    return AjaxResult.success();
                } else {
                    log.error("汇付绑卡确认入库失败");
                }
            } else if (AdaPayConstants.PENDING.equals(resultMap.get("status").toString())) {
                // 返回处理中
                return AjaxResult.success("汇付绑卡处理中，请稍后刷新");
            } else {
                log.error("汇付绑卡确认返回失败! code: {}, msg: {}, invalid_param: {}", resultMap.get("error_code"), resultMap.get("error_msg"), resultMap.get("invalid_param"));
            }
        } catch (Exception e) {
            log.error("调用汇付绑卡确认处理异常!", e);
        }
        return AjaxResult.error("绑卡失败，请刷新后重试");
    }

    /**
     * 确认支付
     *
     * @param param
     * @return
     */
    @RepeatSubmitSimple
    @PostMapping("/pay-confirm")
    public AjaxResult payConfirm(@RequestBody FastPayOrderParam param) {
        if (StringUtils.isAnyEmpty(param.getBindCode(), param.getOrderCode(), param.getSmsCode())) {
            return AjaxResult.error("缺少参数");
        }

        try {
            // 查询用户绑卡信息
            TOnlineCard tOnlineCard = itOnlineCardService.queryCardByCode(param.getBindCode(), SecurityUtils.getUserId(), adaPayConfig.getAppId(), SecurityUtils.getPkCountry());
            if (null == tOnlineCard) {
                return AjaxResult.error("用户未绑定该银行卡");
            }

            // 查询需要流水号
            QueryWrapper<TOnlinePayment> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("BUSINESS_CODE", param.getOrderCode());
            queryWrapper.eq("PAY_CHANNEL", EPayChannel.ADAPAY.getValue());
            queryWrapper.eq("PAY_TYPE", EPayType.BANK_CARD.getValue());
            queryWrapper.eq("PK_CREATOR", SecurityUtils.getUserId());
            TOnlinePayment tOnlinePayment = itOnlinePaymentService.getOne(queryWrapper);
            if (EPayStatus.PAID.getValue() == tOnlinePayment.getPayStatus()) {
                return AjaxResult.error("该订单已支付");
            }

            Map<String, Object> params = new HashMap<>();
            params.put("payment_id", tOnlinePayment.getPayNumber());
            params.put("sms_code", param.getSmsCode());
            params.put("app_id", adaPayConfig.getAppId());

            log.info("汇付快捷确认支付请求参数： {}", params);

            Map<String, Object> resultData = FastPay.confirm(params, adaPayConfig.getAppId());

            log.info("汇付快捷确认支付返回数据： {}", resultData);

            if (AdaPayConstants.SUCCESS.equals(resultData.get("status").toString())) {
                // 返回成功
                return AjaxResult.success("支付已处理，请稍后查看");
            } else {
                log.error("汇付快捷确认支付失败! code: {}, msg: {}, invalid_param: {}", resultData.get("error_code"), resultData.get("error_msg"), resultData.get("invalid_param"));
                return AjaxResult.error(resultData.get("error_msg").toString());
            }
        } catch (Exception e) {
            log.error("汇付快捷确认支付处理异常!", e);
        }
        return AjaxResult.error("支付失败，请刷新后重试");
    }

    /**
     * 查询用户绑卡信息
     *
     * @return
     */
    @GetMapping("/query")
    public AjaxResult query() {
        try {
            QueryWrapper<TOnlineThirdBind> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("PK_MEMBER", SecurityUtils.getUserId());
            queryWrapper.eq("CHANNEL", EPayChannel.ADAPAY.getValue());
            queryWrapper.eq("TYPE", EThirdBindType.PAY_MEMBER.getValue());
            List<TOnlineThirdBind> tOnlineThirdBindList = itOnlineThirdBindService.list(queryWrapper);
            if (CollectionUtil.isEmpty(tOnlineThirdBindList)) {
                return AjaxResult.error("该用户未绑定过汇付银行卡");
            }

            List<HashMap> resultList = new ArrayList<>();

            for (TOnlineThirdBind tOnlineThirdBind : tOnlineThirdBindList) {
                Map<String, Object> params = new HashMap<>();
                params.put("app_id", adaPayConfig.getAppId());
                params.put("member_id", tOnlineThirdBind.getBindInfo());

                log.info("汇付绑卡查询请求参数： {}", params);

                Map<String, Object> resultMap = FastPay.cardList(params, adaPayConfig.getAppId());

                log.info("汇付绑卡查询返回参数： {}", resultMap);

                if (AdaPayConstants.SUCCESS.equals(resultMap.get("status").toString())) {
                    // 返回成功
                    resultList.addAll(JSONUtil.parseArray(resultMap.get("fast_cards")).toList(HashMap.class));
                } else {
                    log.error("汇付绑卡查询返回失败! code: {}, msg: {}, invalid_param: {}", resultMap.get("error_code"), resultMap.get("error_msg"), resultMap.get("invalid_param"));
                    return AjaxResult.error("调用汇付查询绑卡信息失败");
                }
            }
            return AjaxResult.success(resultList);
        } catch (Exception e) {
            log.error("调用汇付绑卡查询处理异常!", e);
        }
        return AjaxResult.error(TransactionUtils.getContent(CommonMsgConstants.OPERATION_FAILED_FLUSH));
    }

    /**
     * 解绑银行卡
     *
     * @param param
     * @return
     */
    @PostMapping("/un-bind")
    public AjaxResult unbind(@RequestBody FastUnBindParam param) {
        if (StringUtils.isEmpty(param.getBindCode())) {
            return AjaxResult.error("缺少参数");
        }

        try {
            // 当前用户
            Long userId = SecurityUtils.getUserId();

            TOnlineCard tOnlineCard = itOnlineCardService.queryCardByCode(param.getBindCode(), userId, adaPayConfig.getAppId(), SecurityUtils.getPkCountry());
            if (null == tOnlineCard) {
                return AjaxResult.error("用户未绑定该银行卡");
            }

            QueryWrapper<TOnlineThirdBind> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("PK_MEMBER", userId);
            queryWrapper.eq("CHANNEL", EPayChannel.ADAPAY.getValue());
            queryWrapper.eq("TYPE", EThirdBindType.PAY_MEMBER.getValue());
            queryWrapper.eq("USER_OTHER", tOnlineCard.getName());
            TOnlineThirdBind tOnlineThirdBind = itOnlineThirdBindService.getOne(queryWrapper);
            if (null == tOnlineThirdBind) {
                return AjaxResult.error("该用户未绑定过汇付银行卡");
            }

            Map<String, Object> params = new HashMap<>();
            params.put("adapay_func_code", "fast_card.unBindCard");
            params.put("order_no", tOnlineCard.getCode());
            params.put("app_id", adaPayConfig.getAppId());
            params.put("member_id", tOnlineThirdBind.getBindInfo());
            params.put("token_no", tOnlineCard.getThirdInfo());
            params.put("notify_url", adaPayConfig.getFastUnbindCallBackUrl());

            log.info("汇付解绑请求参数： {}", params);

            Map<String, Object> resultMap = AdapayCommon.requestAdapayUits(params, adaPayConfig.getAppId());

            log.info("汇付解绑返回参数： {}", resultMap);

            if (AdaPayConstants.SUCCESS.equals(resultMap.get("status").toString())) {
                // 返回成功

                // 解绑银行卡
                itOnlineCardService.unBindBank(tOnlineCard.getCode(), userId, adaPayConfig.getAppId());

                return AjaxResult.success();
            } else if (AdaPayConstants.PENDING.equals(resultMap.get("status").toString())) {
                // 返回处理中
                return AjaxResult.success("汇付绑卡处理中，请稍后刷新");
            } else {
                log.error("汇付绑卡确认返回失败! code: {}, msg: {}, invalid_param: {}", resultMap.get("error_code"), resultMap.get("error_msg"), resultMap.get("invalid_param"));
            }
        } catch (Exception e) {
            log.error("调用汇付解绑处理异常!", e);
        }
        return AjaxResult.error(TransactionUtils.getContent(CommonMsgConstants.OPERATION_FAILED_FLUSH));
    }

}
