package com.jeequan.jeepay.agent.ctrl.aqf;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.response.AlipayFundAccountbookQueryResponse;
import com.jeequan.jeepay.agent.ctrl.CommonCtrl;
import com.jeequan.jeepay.core.cache.RedisUtil;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.TransferOrder;
import com.jeequan.jeepay.core.entity.TransferSubject;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.tranfer.TransferBasicInfo;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.service.impl.SysConfigService;
import com.jeequan.jeepay.service.impl.TransferSubjectService;
import com.jeequan.jeepay.service.impl.TransferWalletService;
import com.jeequan.jeepay.thirdparty.channel.alipay.AliAqfV2Service;
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@RestController
@RequestMapping("/api/aqfApi")
public class AqfApiController extends CommonCtrl {

    @Autowired
    private AliAqfV2Service aliAqfV2Service;

    @Autowired
    private SysConfigService sysConfigService;

    @Autowired
    private TransferSubjectService transferSubjectService;
    @Autowired
    private ChannelCertConfigKitBean channelCertConfigKitBean;
    @Autowired
    private TransferWalletService transferWalletService;

    /**
     * 签约
     *
     * @return
     */
    @RequestMapping(value = "/signUrl", method = RequestMethod.GET)
    public ApiRes signUrl() {
        String subId = getValStringRequired("subId");
        String resutUrl = aliAqfV2Service.userAgreementPageSign(subId);
        return ApiRes.ok(resutUrl);
    }


    /**
     * 支付宝个人代扣协议查询接口
     *
     * @return
     */
    @RequestMapping(value = "/agreementQuery" , method = RequestMethod.GET)
    public ApiRes agreementQuery(){
        String  subId = getValStringRequired("subId");
        JSONObject alipayUserAgreementQueryResponse = aliAqfV2Service.userAgreementQuery(subId);
        return ApiRes.ok(alipayUserAgreementQueryResponse);
    }

    /**
     * 解约
     *
     * @return
     */
    @RequestMapping(value = "/userAgreementUnsign" , method = RequestMethod.GET)
    public ApiRes userAgreementUnsign(){
        String  subId = getValStringRequired("subId");
        JSONObject alipayUserAgreementUnsignResponse = aliAqfV2Service.userAgreementUnsign(subId);
        return ApiRes.ok(alipayUserAgreementUnsignResponse);
    }

    /**
     * 记账本查询
     *
     * @return
     */
    @RequestMapping(value = "/alipayFundAccountbookQuery", method = RequestMethod.GET)
    public ApiRes alipayFundAccountbookQuery() {
        String subId = getValStringRequired("subId");
        String walletApplyId = getValString("walletApplyId");
        // 设计上，一个签约主体可以创建多个记账本，实际使用的时候，尽量保持一个签约主体只有一个账本
        AlipayFundAccountbookQueryResponse alipayFundAccountbookQueryResponse = aliAqfV2Service.fundAccountbookQuery(walletApplyId);
        return ApiRes.ok(JSON.parseObject(alipayFundAccountbookQueryResponse.getBody()).getJSONObject("alipay_fund_accountbook_query_response"));
    }

    /**
     * 资金专款拨入（商户自身给记账本充值）
     *
     * @return
     */
    @RequestMapping(value = "/transPage" , method = RequestMethod.GET)
    public ApiRes transPage(){
        String  subId = getValStringRequired("subId");
        String transAmount = getValStringRequired("transAmount");
        String transferDesc = getValString("transferDesc");
        String transedUrl = aliAqfV2Service.transPage(subId, transAmount,transferDesc);
        return ApiRes.ok(transedUrl);
    }

    /**
     * 单笔生成待发待结算信息
     *
     * @return
     */
    @RequestMapping(value = "/settlementData", method = RequestMethod.POST)
    public ApiRes settlementDate() {
        String currentAgentNo = getCurrentAgentNo();
        String transferSubjectIdFq = getValStringRequired("transferSubjectIdFq");
        String vc = Base64.decodeStr(getValStringRequired("vc"));
        String vt = Base64.decodeStr(getValStringRequired("vt"));
        String sipw = Base64.decodeStr(getValStringRequired("sipw"));

        // 验证码校验
        String cacheCode = RedisUtil.getString(CS.getCacheKeyImgCode(vt));
        if(StringUtils.isEmpty(cacheCode) || !cacheCode.equalsIgnoreCase(vc)){
            throw new BizException("验证码有误！");
        }

        TransferSubjectEntity transferSubject = transferSubjectService.getById(transferSubjectIdFq);
        if (!transferSubject.getInfoType().equals(CS.SYS_ROLE_TYPE.AGENT)
                || !currentAgentNo.equals(transferSubject.getAgentNo())) {
            throw new BizException("非法操作");
        }

        AgentInfo agentInfo = agentInfoService.getById(transferSubject.getAgentNo());
        if (!sipw.equals(agentInfo.getSipw())) {
            throw new BizException("支付密码校验失败");
        }

        SettlementDataModel object = getObject(SettlementDataModel.class);

        String date = aliAqfV2Service.settlementData(object.getTransferSubjectIdFq(), object.getTransferOrders());
        return ApiRes.ok(date);
    }

    /**
     * 批量生成待结算数据,先入库再发起结算
     */
    @PostMapping("/batchSettlementData")
    public ApiRes uploadExcel() {

        String currentAgentNo = getCurrentAgentNo();

        String transferSubjectIdFq = getValStringRequired("transferSubjectIdFq");
        String excelFileName = getValStringRequired("excelFileName");
        File excelFile = channelCertConfigKitBean.getCertFile(excelFileName);

        SettlementDataModel params = getObject(SettlementDataModel.class);

        String vc = Base64.decodeStr(getValStringRequired("vc"));
        String vt = Base64.decodeStr(getValStringRequired("vt"));
        String sipw = Base64.decodeStr(getValStringRequired("sipw"));

        // 验证码校验
        String cacheCode = RedisUtil.getString(CS.getCacheKeyImgCode(vt));
        if(StringUtils.isEmpty(cacheCode) || !cacheCode.equalsIgnoreCase(vc)){
            throw new BizException("验证码有误！");
        }

        TransferSubjectEntity transferSubject = transferSubjectService.getById(transferSubjectIdFq);
        if (!transferSubject.getInfoType().equals(CS.SYS_ROLE_TYPE.AGENT)
                || !currentAgentNo.equals(transferSubject.getAgentNo())) {
            throw new BizException("非法操作");
        }

        AgentInfo agentInfo = agentInfoService.getById(transferSubject.getAgentNo());
        if (!sipw.equals(agentInfo.getSipw())) {
            throw new BizException("支付密码校验失败");
        }

        List<SettleBatchExcel> dataList = new ArrayList<>();
        List<TransferOrder> transferOrderList = new ArrayList<>();
        String batch = "BATCH" + DateUtil.format(new Date(), "yyMMdd") + RandomUtil.randomNumbers(6);
        try {
            InputStream inputStream = Files.newInputStream(excelFile.toPath());
            EasyExcel.read(inputStream, SettleBatchExcel.class, new AnalysisEventListener<SettleBatchExcel>() {
                @Override
                public void invoke(SettleBatchExcel settleBatchExcel, AnalysisContext analysisContext) {
                    dataList.add(settleBatchExcel);
                }

                @Override
                public void doAfterAllAnalysed(AnalysisContext context) {
                    // 解析完成后的操作，可以在这里进行一些清理工作
                }
            }).sheet().doRead();
            //把数据新增到收款信息中
            Assert.notEmpty(params.getTaskId(), "任务号不能为空");

            TransferSubjectEntity sponsor = transferSubjectService.getById(params.getTransferSubjectIdFq());
            if (!getCurrentAgentNo().equalsIgnoreCase(sponsor.getAgentNo())) {
                throw new BizException("参数非法");
            }

            if (!Objects.equals(sponsor.getState(), TransferSubject.STATE_ENABLE)) {
                throw new BizException("付款账户当前状态不可用");
            }

            if (!Objects.equals(sponsor.getSignState(), (int) TransferSubject.SIGN_STATE_SUCCESS)) {
                throw new BizException("付款账户暂未完成签约");
            }

            TransferWalletEntity transferWallet = transferWalletService.getByApplyId(sponsor.getTransApplyId(), null);
            String extCardInfo = transferWallet.getExtCardInfo();

            JSONObject extCardJSON = JSONObject.parseObject(extCardInfo);

            Assert.notNull(sponsor, "未获取到对应的转账发起方信息");

            for (SettleBatchExcel settleBatchExcel : dataList) {
                TransferSubjectEntity receiver = transferSubjectService.getReceiver(sponsor.getIsvNo(),
                        CS.IF_CODE.ALIAQF, CS.SYS_ROLE_TYPE.AGENT, getCurrentAgentNo(), settleBatchExcel.getAccountNo(),
                        settleBatchExcel.getEntryType(), settleBatchExcel.getAccountType());
                if (receiver == null) {
                    // 先存储转账接受账户信息
                    receiver = new TransferSubjectEntity();
                    receiver.setId("SUB" + DateUtil.format(new Date(), "yyMMdd") + RandomUtil.randomNumbers(6));
                    receiver.setAccount(settleBatchExcel.getAccountNo());
                    receiver.setState(TransferSubject.STATE_ENABLE);
                    receiver.setSubjectType(TransferSubject.SUBJECT_TYPE_RECEIVER);
                    receiver.setIsvNo(sponsor.getIsvNo());
                    receiver.setInfoType(sponsor.getInfoType());
                    receiver.setMchNo(sponsor.getMchNo());
                    receiver.setAgentNo(sponsor.getAgentNo());
                    receiver.setAgentName(sponsor.getAgentName());
                    receiver.setTopAgentNo(sponsor.getTopAgentNo());
                    receiver.setTransIfCode(sponsor.getTransIfCode());
                    receiver.setSignState(sponsor.getSignState());
                    receiver.setAccountName(settleBatchExcel.getAccountName());
                    receiver.setAccountType(settleBatchExcel.getAccountType());
                    receiver.setEntryType(settleBatchExcel.getEntryType());
                    transferSubjectService.save(receiver);

                    if (TransferBasicInfo.ENTRY_TYPE_BANK.equalsIgnoreCase(settleBatchExcel.getEntryType())) {
                        // 保存银联支行信息
                        JSONObject bankCardBranchInfo = new JSONObject();
                        if (settleBatchExcel.getInstCity() != null) {
                            bankCardBranchInfo.put("instName", settleBatchExcel.getInstName());
                            bankCardBranchInfo.put("instProvince", settleBatchExcel.getInstProvince());
                            bankCardBranchInfo.put("instCity", settleBatchExcel.getInstCity());
                            bankCardBranchInfo.put("instBranchName", settleBatchExcel.getInstBranchName());
                        }

                        receiver.setAccountMessage(bankCardBranchInfo.toJSONString());
                    }
                }

                // 保存一些订单信息
                TransferOrder transferOrder = new TransferOrder();
                transferOrder.setMchNo(sponsor.getMchNo());
                transferOrder.setIsvNo(sponsor.getIsvNo());
                transferOrder.setAgentNo(sponsor.getAgentNo());
                transferOrder.setTransferSubjectIdFq(params.getTransferSubjectIdFq());
                transferOrder.setTransferSubjectIdJs(receiver.getId());
                transferOrder.setIfCode(receiver.getTransIfCode());
                transferOrder.setWalletId(transferWallet.getId());
                transferOrder.setEntryType(settleBatchExcel.getEntryType());
                transferOrder.setAccountType(settleBatchExcel.getAccountType());
                transferOrder.setAccountName(settleBatchExcel.getAccountName());
                transferOrder.setAccountNo(settleBatchExcel.getAccountNo());
                transferOrder.setOriginAccountNo(sponsor.getAccount());
                transferOrder.setOriginAccountName(sponsor.getAccountName());
                transferOrder.setBatchId(batch);
                transferOrderList.add(transferOrder);
            }
            //新增或更新完毕后发起结算

            aliAqfV2Service.settlementData(params.getTransferSubjectIdFq(), transferOrderList);

        } catch (IOException e) {
            logger.info("批量导入安全发代发数据解析失败！");
            // 处理异常
        }
        // 对 dataList 进行后续操作，如存储到数据库等
        return ApiRes.ok();
    }

//    /**
//     * 代发到户 --不直接调用
//     * @return
//     */
//    @RequestMapping(value = "/transUniTransfer" , method = RequestMethod.GET)
//    public ApiRes transUniTransfer(){
//        String  ersubId = getValStringRequired("ersubId");
//        String  eesubId = getValStringRequired("eesubId");
//        String transAmount = getValStringRequired("transAmount");
//        String taskId = getValStringRequired("taskId");
//        String transferDesc = getValString("transferDesc");
//        AlipayFundTransUniTransferResponse alipayFundTransUniTransferResponse = aliAqfV2Service.transUniTransfer(ersubId, eesubId, getDefaultIsvConfig(), transAmount,taskId,null,transferDesc);
//        return ApiRes.ok(alipayFundTransUniTransferResponse);
//    }

//    /**
//     * 代发到卡 --不直接调用
//     * @return
//     */
//    @RequestMapping(value = "/transUniTransferCard" , method = RequestMethod.GET)
//    public ApiRes transUniTransferCard(){
//        String  ersubId = getValStringRequired("ersubId");
//        String  eesubId = getValStringRequired("eesubId");
//        String transAmount = getValStringRequired("transAmount");
//        String taskId = getValStringRequired("taskId");
//        String transferDesc = getValString("transferDesc");
//        AlipayFundTransUniTransferResponse alipayFundTransUniTransferResponse = aliAqfV2Service.transUniTransferCard(ersubId, eesubId, getDefaultIsvConfig(), transAmount, taskId,null,transferDesc);
//        return ApiRes.ok(alipayFundTransUniTransferResponse);
//    }

    /**
     * 账单查询
     *
     * @return
     */
    @RequestMapping(value = "/bizfundagentQuery", method = RequestMethod.GET)
    public ApiRes bizfundagentQuery() {
        String ersubId = getValStringRequired("ersubId");
        String startTime = getValStringRequired("startTime");
        String endTime = getValStringRequired("endTime");
        String pageNo = getValStringRequired("pageNo");
        String pageSize = getValStringRequired("pageSize");
        JSONObject alipayDataBillBizfundagentQueryResponse = aliAqfV2Service.bizfundagentQuery(ersubId, startTime, endTime, pageNo, pageSize);
        return ApiRes.ok(alipayDataBillBizfundagentQueryResponse);
    }

    /**
     * 电子回单申请
     *
     * @return
     */
    @RequestMapping(value = "/applicationForm", method = RequestMethod.GET)
    public ApiRes applicationForm() {

        String ersubId = getValStringRequired("ersubId");
        String transferId = getValStringRequired("transferId");
        JSONObject alipayDataBillEreceiptagentApplyResponse = aliAqfV2Service.applicationForm(ersubId, transferId);
        return ApiRes.ok(alipayDataBillEreceiptagentApplyResponse);
    }

    /**
     * 电子回单下载地址获取
     *
     * @return
     */
    @RequestMapping(value = "/applicationFormDownload", method = RequestMethod.GET)
    public ApiRes applicationFormDownload() {
        String ersubId = getValStringRequired("ersubId");
        String transferId = getValStringRequired("transferId");
        JSONObject alipayDataBillAccountbookereceiptQueryResponse = aliAqfV2Service.applicationFormDownload(ersubId, transferId);
        return ApiRes.ok(alipayDataBillAccountbookereceiptQueryResponse);
    }

    public String getDefaultIsvConfig() {
        SysConfig serviceOne = sysConfigService.getOne(SysConfig.gw().eq(SysConfig::getGroupKey, "defaultConfig")
                .eq(SysConfig::getConfigKey, "defaultIsvNo"));
        if (serviceOne != null) {
            return serviceOne.getConfigVal();
        }
        return null;
    }
    /**
     * 根据付款人信息id获取详情
     */
    public TransferSubjectEntity getSubjectOne(String subId){
        TransferSubjectEntity transferSubjectEntity = transferSubjectService.getById(subId);
        if (transferSubjectEntity != null){
            return transferSubjectEntity;
        }else {
            throw new BizException("未查询到当前付款人信息！");
        }
    }
}
