package com.jeequan.jeepay.thirdparty.channel.zftpay;

import cn.hutool.core.io.resource.BytesResource;
import cn.hutool.core.util.ObjUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.domain.*;
import com.alipay.api.request.AntMerchantExpandIndirectZftDeleteRequest;
import com.alipay.api.request.AntMerchantExpandIndirectZftorderQueryRequest;
import com.alipay.api.response.AntMerchantExpandIndirectZftDeleteResponse;
import com.alipay.api.response.AntMerchantExpandIndirectZftorderQueryResponse;
import com.jeequan.jeepay.core.entity.MchApplyment;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.interfaces.paychannel.IIsvmchApplymentService;
import com.jeequan.jeepay.core.model.applyment.ApplymentSignInfo;
import com.jeequan.jeepay.core.model.applyment.ZftpayApplymentInfo;
import com.jeequan.jeepay.core.model.params.zftpay.ZftpayIsvParams;
import com.jeequan.jeepay.db.entity.BankBranchZft;
import com.jeequan.jeepay.service.impl.BankBranchZftService;
import com.jeequan.jeepay.service.impl.MchApplymentService;
import com.jeequan.jeepay.thirdparty.channel.zftpay.model.Const;
import com.jeequan.jeepay.thirdparty.channel.zftpay.model.ReqMethod;
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service("zftpayMchApplymentService")
public class ZftpayMchApplymentService implements IIsvmchApplymentService<ZftpayApplymentInfo> {

    @Autowired
    private ConfigContextQueryService configContextQueryService;

    @Autowired
    private BankBranchZftService bankBranchZftService;
    @Autowired
    private MchApplymentService mchApplymentService;

    public AntMerchantExpandIndirectZftCreateModel getApplymentParams(MchApplyment mchApplyment) {
        JSONObject result = new JSONObject();
        List<BytesResource> files = new ArrayList<>();
        result.put("files", files);
        ZftpayApplymentInfo applymentInfo = JSON.parseObject(mchApplyment.getApplyDetailInfo(), ZftpayApplymentInfo.class);

        ZftpayIsvParams isvParams = ((ZftpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment));


        if ("Y".equals(applymentInfo.getAuthSettle())) {
            throw new BizException("直付通入网不支持非法人结算");
        }

        AntMerchantExpandIndirectZftCreateModel zftMerchInfo = new AntMerchantExpandIndirectZftCreateModel();

        zftMerchInfo.setExternalId(mchApplyment.getApplyId());
        switch (applymentInfo.getMerchantType()) {
            case MchApplyment.MERCHANT_TYPE_PERSONAL:
                zftMerchInfo.setMerchantType("06");
                zftMerchInfo.setCertType("100");
                zftMerchInfo.setCertNo(applymentInfo.getIdcardNo());
                zftMerchInfo.setCertName(applymentInfo.getIdcardName());
                zftMerchInfo.setName(applymentInfo.getIdcardName());
                break;
            case MchApplyment.MERCHANT_TYPE_INDIVIDUAL:
                zftMerchInfo.setMerchantType("07");
                zftMerchInfo.setCertType("201");
                zftMerchInfo.setCertNo(applymentInfo.getLicenseNo());
                zftMerchInfo.setCertName(applymentInfo.getMchFullName());
                // 个体户使用法人名称
                zftMerchInfo.setName(applymentInfo.getIdcardName());
                break;
            case MchApplyment.MERCHANT_TYPE_ENTERPRISE:
                zftMerchInfo.setMerchantType("01");
                zftMerchInfo.setCertType("201");
                zftMerchInfo.setCertNo(applymentInfo.getLicenseNo());
                zftMerchInfo.setCertName(applymentInfo.getLicenseName());
                zftMerchInfo.setName(applymentInfo.getMchFullName());
                break;
            default:
                throw new BizException("未知商户类型");
        }

        Assert.notNull(applymentInfo.getIdcard1Img(), "身份证人像面图片不能为空");
        Assert.notNull(applymentInfo.getIdcard2Img(), "身份证国徽面图片不能为空");
        if (mchApplyment.getMerchantType() != MchApplyment.MERCHANT_TYPE_PERSONAL) {
            Assert.notNull(applymentInfo.getLicenseImg(), "营业执照图片不能为空");
            zftMerchInfo.setCertImage(upload(isvParams, applymentInfo.getLicenseImg()));
            zftMerchInfo.setLegalName(applymentInfo.getIdcardName());
            zftMerchInfo.setLegalCertNo(applymentInfo.getIdcardNo());

            zftMerchInfo.setLegalCertFrontImage(upload(isvParams, applymentInfo.getIdcard1Img()));
            Assert.notNull(applymentInfo.getIdcard2Img(), "身份证国徽面图片不能为空");
            zftMerchInfo.setLegalCertBackImage(upload(isvParams, applymentInfo.getIdcard2Img()));
        } else {
            // 小微需要上传身份证
            zftMerchInfo.setCertImage(upload(isvParams, applymentInfo.getIdcard1Img()));
            zftMerchInfo.setCertImageBack(upload(isvParams, applymentInfo.getIdcard2Img()));
            Assert.notNull(applymentInfo.getAlipayLogonId(), "个人商户只能结算到支付宝账户");
        }

        AddressInfo businessAddress = new AddressInfo();
        businessAddress.setProvinceCode(applymentInfo.getAreaCode().getString(0));
        businessAddress.setCityCode(applymentInfo.getAreaCode().getString(1));
        businessAddress.setDistrictCode(applymentInfo.getAreaCode().getString(2));
        businessAddress.setAddress(applymentInfo.getAddress());
        zftMerchInfo.setBusinessAddress(businessAddress);

        zftMerchInfo.setAliasName(applymentInfo.getMchShortName());

        Assert.notNull(applymentInfo.getMccCode(), "mcc不能为空");
        String[] mccData = applymentInfo.getMccCode().split("_");
        if (mccData.length < 2) {
            throw new BizException("mcc格式错误");
        }
        zftMerchInfo.setMcc(mccData[1]);

        List<ContactInfo> contactInfosList = new ArrayList<>();
        ContactInfo contactInfo = new ContactInfo();
        contactInfo.setName(mchApplyment.getContactName());
        contactInfo.setPhone(mchApplyment.getContactPhone());
        contactInfo.setMobile(applymentInfo.getContactPhone());
        contactInfo.setIdCardNo(applymentInfo.getSettAccountIdcardNo());
        contactInfosList.add(contactInfo);
        zftMerchInfo.setMerchantType(applymentInfo.convertMerchantType());


        if (!"alipayAccount".equals(applymentInfo.getDefaultSettleType())
                && MchApplyment.MERCHANT_TYPE_PERSONAL != applymentInfo.getMerchantType()) {
            SettleCardInfo bizCard = getBizCards(applymentInfo);

            // 企业对私，需要授权函
            if (Objects.equals(applymentInfo.getMerchantType(), MchApplyment.MERCHANT_TYPE_ENTERPRISE)
                    && MchApplyment.SETT_ACCOUNT_TYPE_PERSONAL.equals(applymentInfo.getSettAccountType())) {
                zftMerchInfo.setLicenseAuthLetterImage(upload(isvParams, applymentInfo.getLicenseAuthLetterImage()));
            }

            // 小微商户不能使用银行卡结算
            zftMerchInfo.setBizCards(Collections.singletonList(bizCard));
            zftMerchInfo.setLegalName(applymentInfo.getIdcardName());
            zftMerchInfo.setLegalCertNo(applymentInfo.getIdcardNo());
            zftMerchInfo.setLegalCertFrontImage(upload(isvParams, applymentInfo.getIdcard1Img()));
        } else {
            zftMerchInfo.setAlipayLogonId(applymentInfo.getAlipayLogonId());
        }

        zftMerchInfo.setCertImageBack(upload(isvParams, applymentInfo.getIdcard2Img()));

        List<IndustryQualificationInfo> qualifications = getQualifications(applymentInfo, isvParams);
        zftMerchInfo.setQualifications(qualifications);
        zftMerchInfo.setService(applymentInfo.getServiceList());


        zftMerchInfo.setBindingAlipayLogonId(applymentInfo.getBindingAlipayLogonId());
        zftMerchInfo.setContactInfos(contactInfosList);

        List<String> inDoorImages = new ArrayList<>();
        inDoorImages.add(upload(isvParams, applymentInfo.getStoreInnerImg()));
        zftMerchInfo.setInDoorImages(inDoorImages);

        List<String> outDoorImages = new ArrayList<>();
        outDoorImages.add(upload(isvParams, applymentInfo.getStoreOuterImg()));
        zftMerchInfo.setOutDoorImages(outDoorImages);

        DefaultSettleRule defaultSettleRule = new DefaultSettleRule();
        defaultSettleRule.setDefaultSettleType(applymentInfo.getDefaultSettleType());
        if ("alipayAccount".equals(applymentInfo.getDefaultSettleType())) {
            // 结算到支付宝
            defaultSettleRule.setDefaultSettleTarget(applymentInfo.getAlipayLogonId());
        } else {
            // 结算到银行卡
            defaultSettleRule.setDefaultSettleTarget(applymentInfo.getSettAccountNo());
        }

        zftMerchInfo.setDefaultSettleRule(defaultSettleRule);
        zftMerchInfo.setContactInfos(contactInfosList);
        zftMerchInfo.setSites(applymentInfo.getSiteInfos().toJavaList(SiteInfo.class));
//        zftMerchInfo.put("sites", getSites(applymentInfo));

        return zftMerchInfo;
    }

    private static List<JSONObject> getSites(ZftpayApplymentInfo applymentInfo) {
        JSONArray siteInfos = applymentInfo.getSiteInfos();

        List<JSONObject> sites = new ArrayList<>();
        JSONObject item = new JSONObject();
        item.put("site_type", "01");
        item.put("site_url", "https://b.rscygroup.com/");
        item.put("site_name", "商福通");
        sites.add(item);

        item = new JSONObject();
        item.put("site_type", "02");
        item.put("site_name", "商福通");
        sites.add(item);
        return sites;
    }

    /**
     * 特殊资质信息
     * @param applymentInfo 商户信息
     */
    private List<IndustryQualificationInfo> getQualifications(ZftpayApplymentInfo applymentInfo, ZftpayIsvParams isvParams) {
        if (ObjUtil.isEmpty(applymentInfo.getIndustryQualificationType())) {
            return new ArrayList<>();
        } else {
            if (ObjUtil.isEmpty(applymentInfo.getIndustryQualificationImage())) {
                throw new BizException("商户行业资质图片不能为空");
            }

            IndustryQualificationInfo industryQualificationType = new IndustryQualificationInfo();
            industryQualificationType.setIndustryQualificationType(applymentInfo.getIndustryQualificationType());
            industryQualificationType.setIndustryQualificationImage(upload(isvParams, applymentInfo.getIndustryQualificationImage()));

            return Collections.singletonList(industryQualificationType);
        }
    }

    private SettleCardInfo getBizCards(ZftpayApplymentInfo applymentInfo) {

        SettleCardInfo bizCard = new SettleCardInfo();

        String accountType = applymentInfo.getUseType();

        bizCard.setAccountHolderName(applymentInfo.getSettAccountName());
        Assert.notNull(applymentInfo.getSettAccountBankBranchAreaName(), "开户行地区省市名称【settAccountBankBranchAreaName】不能为空");
        Assert.isTrue(applymentInfo.getSettAccountBankBranchAreaName().size() >= 2, "开户行地区省市名称有误");
        bizCard.setAccountInstProvince(applymentInfo.getSettAccountBankBranchAreaName().getString(0));
        bizCard.setAccountInstCity(applymentInfo.getSettAccountBankBranchAreaName().getString(1));
        bizCard.setAccountBranchName(applymentInfo.getSettAccountBankBranchName());
        bizCard.setUsageType(accountType);

        bizCard.setAccountType("DC");
        bizCard.setAccountInstName("DC");

        Assert.notNull(applymentInfo.getSettAccountBankBranchCode(), "支行联行号不能为空");
        BankBranchZft branchZft = bankBranchZftService.lambdaQuery()
                .eq(BankBranchZft::getBranchNo, applymentInfo.getSettAccountBankBranchCode())
                .one();

        Assert.notNull(branchZft, "未找到支行信息");
        bizCard.setAccountInstName(branchZft.getBankName());
        bizCard.setAccountInstId(branchZft.getBankAbbr());
        bizCard.setBankCode(branchZft.getBranchNo());
        bizCard.setAccountNo(applymentInfo.getSettAccountNo());

        return bizCard;
    }

    private String upload(ZftpayIsvParams isvParams, String imgUrl) {
        Assert.isTrue(!ObjectUtils.isEmpty(imgUrl), "【直付通】上传图片链接不能为空");
        JSONObject uploadResult = ZftpayKit.reqUpload(isvParams, ReqMethod.AUDIT_IMG_UPLOAD, imgUrl);
        Assert.notNull(uploadResult, "直付通图片上传异常失败");
        return uploadResult.getString(Const.IMAGE_ID);
    }

    @Override
    public MchApplyment firstApplyment(MchApplyment mchApplyment) {
        return IIsvmchApplymentService.super.firstApplyment(mchApplyment);
    }

    @Override
    public MchApplyment rejectModify(MchApplyment mchApplyment) {
        return firstApplyment(mchApplyment);
    }

    @Override
    public MchApplyment replenishInfo(MchApplyment mchApplyment) {
        return null;
    }

    @Override
    public MchApplyment query(MchApplyment mchApplyment) {
        MchApplyment result = new MchApplyment();
        result.setApplyId(mchApplyment.getApplyId());
        result.setState(mchApplyment.getState());

        ZftpayIsvParams isvParams = (ZftpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment);
        JSONObject reqParams = new JSONObject();
        if (ObjUtil.isEmpty(mchApplyment.getChannelApplyNo())) {
            throw new BizException("未获取到直付通通道请求流水号");
        }

        AntMerchantExpandIndirectZftorderQueryModel zftorderQueryModel = new AntMerchantExpandIndirectZftorderQueryModel();
        zftorderQueryModel.setOrderId(mchApplyment.getChannelApplyNo());
        AntMerchantExpandIndirectZftorderQueryRequest queryRequest = new AntMerchantExpandIndirectZftorderQueryRequest();
        queryRequest.setBizModel(zftorderQueryModel);
        AntMerchantExpandIndirectZftorderQueryResponse resp = ZftpayKit.req(isvParams, queryRequest);
        List<ZftSubMerchantOrder> orders = resp.getOrders();

        for (int i = 0; i < orders.size(); i++) {
            ZftSubMerchantOrder order = orders.get(i);
            if (!mchApplyment.getChannelApplyNo().equals(order.getOrderId())) {
                break;
            } else {
                result.setChannelVar1(JSON.toJSONString(order));
            }

            JSONObject channelVar2 = ((JSONObject) JSON.toJSON(order));
            String status = order.getStatus();
            String fkAudit = order.getFkAudit();
            String kzAudit = order.getKzAudit();
            String subConfirm = order.getSubConfirm();

            // 审核最终状态
            if ("99".equals(status)) {
                // 审核通过
                String smid = order.getSmid();
                result.setState(MchApplyment.STATE_SUCCESS);
                result.setChannelMchNo(smid);

                return result;
            }

            if ("-1".equals(status)) {
                // 审核驳回
                String reason = order.getReason();
                result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
                result.setApplyErrorInfo("[" + reason + "]");
                return result;
            }

            // 签约状态, 已发起商户确认
            if ("CREATE".equals(subConfirm)) {
                // 待签约确认
                // 签约链接
                String subSignQrCodeUrl = order.getSubSignQrCodeUrl();
                channelVar2.put("signUrl", subSignQrCodeUrl);
                result.setChannelVar2(channelVar2.toJSONString());
                result.setState(MchApplyment.STATE_WAIT_SIGN);

                return result;
            }

            // 其他状态暂不处理
        }


        return result;
    }

    @Override
    public ApplymentSignInfo signInfo(MchApplyment mchApplyment) {
        return null;
    }

    @Override
    public void cancel(MchApplyment mchApplyment) {
        if (ObjUtil.isEmpty(mchApplyment.getApplyId())) {
            throw new BizException("进件号不能为空");
        }

        ZftpayIsvParams isvParams = ((ZftpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment));
        // 直付通二级商户作废
        String channelMchNo = mchApplyment.getChannelMchNo();
        JSONObject param = new JSONObject();
        AntMerchantExpandIndirectZftDeleteModel model = new AntMerchantExpandIndirectZftDeleteModel();
        model.setSmid(channelMchNo);
        AntMerchantExpandIndirectZftDeleteRequest request = new AntMerchantExpandIndirectZftDeleteRequest();
        request.setBizModel(model);

        AntMerchantExpandIndirectZftDeleteResponse response = ZftpayKit.req(isvParams, request);

        // 更新商户状态
        mchApplymentService.lambdaUpdate()
                .eq(com.jeequan.jeepay.db.entity.MchApplyment::getApplyId, mchApplyment.getApplyId())
                .set(com.jeequan.jeepay.db.entity.MchApplyment::getState, MchApplyment.STATE_WAIT_LOGOUT)
                .update();
    }
}
