package com.czg.third.wechat;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONWriter;
import com.czg.PayCst;
import com.czg.dto.req.*;
import com.czg.dto.resp.EntryThirdRespDto;
import com.czg.dto.resp.QueryStatusResp;
import com.czg.dto.resp.WechatBankBranchRespDto;
import com.czg.exception.CzgException;
import com.czg.third.wechat.dto.config.WechatPayConfigDto;
import com.czg.third.wechat.dto.req.entry.*;
import com.czg.third.wechat.dto.req.entry.business.WechatEntryBusinessReqDto;
import com.czg.third.wechat.dto.req.entry.business.WechatEntryIdentityReqDto;
import com.czg.third.wechat.dto.req.entry.business.WechatEntryLicenseReqDto;
import com.czg.third.wechat.dto.req.entry.business.sales.WechatEntryMiniProgramReqDto;
import com.czg.third.wechat.dto.req.entry.business.sales.WechatEntrySalesInfoReqDto;
import com.czg.third.wechat.dto.req.entry.business.sales.WechatEntryStoreInfoReqDto;
import com.czg.third.wechat.dto.req.entry.business.sales.WechatEntryWebInfoReqDto;
import com.czg.third.wechat.dto.req.entry.id.WechatEntryIdCardReqDto;
import com.czg.third.wechat.dto.resp.WechatAuditDetail;
import com.czg.third.wechat.dto.resp.WechatQueryStateResp;
import com.czg.utils.UploadFileUtil;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.cipher.PrivacyEncryptor;
import com.wechat.pay.java.core.exception.MalformedMessageException;
import com.wechat.pay.java.service.file.FileUploadService;
import com.wechat.pay.java.service.file.model.FileUploadResponse;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * 微信支付进件 管理
 * 参考地址 <a href="https://pay.weixin.qq.com/doc/v3/partner/4012719997">...</a>
 *
 * @author yjjie
 * @date 2025/12/26 10:57
 */
@Slf4j
public class WechatEntryManager {

    /**
     * 查询商户进件状态
     *
     * @param configDto 配置信息
     * @param applyId   自系统的商户编号
     * @return 进件状态
     */
    public static QueryStatusResp queryMerchantEntryStatus(WechatPayConfigDto configDto, String applyId) {
        QueryStatusResp queryStatusResp = new QueryStatusResp();
        queryStatusResp.setPlatform(PayCst.Type.WECHAT);
        queryStatusResp.setMerchantCode(applyId);

        String resp = WechatReqUtils.getReq(configDto, "/v3/applyment4sub/applyment/applyment_id/" + applyId, Map.of());
        JSONObject object = JSONObject.parseObject(resp);
        if (resp.contains("message")) {
            log.error("微信查询进件状态失败：{}", resp);
            queryStatusResp.setFailReason(object.getString("message"));
            queryStatusResp.setStatus(PayCst.EntryStatus.REJECTED);
            return queryStatusResp;
        }
        log.info("微信查询进件状态：{}", resp);
        WechatQueryStateResp stateResp = JSONObject.parseObject(resp, WechatQueryStateResp.class);

        queryStatusResp.setApplyId(stateResp.getApplyId());
        switch (stateResp.getApplyState()) {
            case "APPLYMENT_STATE_EDITTING" -> {
                queryStatusResp.setStatus(PayCst.EntryStatus.WAIT);
                queryStatusResp.setFailReason("");
            }
            case "APPLYMENT_STATE_AUDITING" -> {
                queryStatusResp.setStatus(PayCst.EntryStatus.AUDIT);
                queryStatusResp.setFailReason("");
                queryStatusResp.setSignUrl(stateResp.getSignUrl());
                if (StrUtil.isNotBlank(queryStatusResp.getSignUrl())) {
                    queryStatusResp.setStatus(PayCst.EntryStatus.SIGN);
                }
            }
            case "APPLYMENT_STATE_REJECTED" -> {
                queryStatusResp.setStatus(PayCst.EntryStatus.REJECTED);
                StringBuilder msg = new StringBuilder();
                for (WechatAuditDetail auditDetail : stateResp.getAuditDetail()) {
                    msg.append(auditDetail.getRejectReason()).append("，");
                }
                queryStatusResp.setFailReason(msg.toString());
            }
            case "APPLYMENT_STATE_TO_BE_CONFIRMED", "APPLYMENT_STATE_TO_BE_SIGNED" -> {
                queryStatusResp.setStatus(PayCst.EntryStatus.SIGN);
                queryStatusResp.setFailReason("");
                queryStatusResp.setSignUrl(stateResp.getSignUrl());
            }
            case "APPLYMENT_STATE_SIGNING", "APPLYMENT_STATE_FINISHED" -> {
                queryStatusResp.setStatus(PayCst.EntryStatus.FINISH);
                queryStatusResp.setFailReason("");
                queryStatusResp.setThirdMerchantId(stateResp.getSubMchId());
            }
        }

        return queryStatusResp;
    }

    /**
     * 进件商户
     *
     * @param configDto 配置信息
     * @param reqDto    请求信息
     */
    public static EntryThirdRespDto entryMerchant(WechatPayConfigDto configDto, AggregateMerchantDto reqDto) {
        EntryThirdRespDto respDto = new EntryThirdRespDto()
                .setPlatform(PayCst.Type.WECHAT);
        try {
            WechatEntryReqDto entryReqDto = buildEntryParams(configDto, reqDto);
            log.info("微信进件参数：{}", JSONObject.toJSONString(entryReqDto));

            String params = JSONObject.toJSONString(entryReqDto, JSONWriter.Feature.IgnoreEmpty);
            String respBody = WechatReqUtils.postReq(configDto, "/v3/applyment4sub/applyment/", params);
            JSONObject object = JSONObject.parseObject(respBody);
            log.info("微信进件结果：{}", respBody);
            if (respBody.contains("applyment_id")) {
                respDto.setStatus(PayCst.EntryStatus.INIT);
                respDto.setEntryId(object.getString("applyment_id"));
                respDto.setErrorMsg("");
            } else {
                respDto.setStatus(PayCst.EntryStatus.REJECTED);
                respDto.setEntryId("");
                respDto.setErrorMsg(object.getString("message"));
            }
        } catch (Exception e) {
            log.error("微信进件报错：{}", e.getMessage());
            respDto.setStatus(PayCst.EntryStatus.REJECTED);
            respDto.setEntryId("");
            respDto.setErrorMsg(e.getMessage());
        }

        return respDto;
    }

    public static JSONObject queryBankList(WechatPayConfigDto configDto, Integer offset, Integer limit) {
        String resp = WechatReqUtils.getReq(configDto, "/v3/capital/capitallhh/banks/corporate-banking", Map.of("offset", offset, "limit", limit));
        log.info("微信查询银行列表：{}", resp);
        return JSONObject.parseObject(resp);
    }

    public static WechatBankBranchRespDto queryBankBranchList(WechatPayConfigDto configDto, String bankAliceCode, String cityCode, Integer offset, Integer limit) {
        String resp = WechatReqUtils.getReq(configDto, "/v3/capital/capitallhh/banks/" + bankAliceCode + "/branches", Map.of("city_code", cityCode, "offset", offset, "limit", limit));
        log.info("微信查询银行支行列表：{}", resp);
        return JSONObject.parseObject(resp, WechatBankBranchRespDto.class);
    }

    public static JSONObject queryProvinceList(WechatPayConfigDto configDto) {
        String resp = WechatReqUtils.getReq(configDto, "/v3/capital/capitallhh/areas/provinces", Map.of());
        log.info("微信查询省份列表：{}", resp);
        return JSONObject.parseObject(resp);
    }

    public static JSONObject queryCityList(WechatPayConfigDto configDto, String provinceCode) {
        String resp = WechatReqUtils.getReq(configDto, "/v3/capital/capitallhh/areas/provinces/" + provinceCode + "/cities", Map.of());
        log.info("微信查询城市列表：{}", resp);
        return JSONObject.parseObject(resp);
    }


    /**
     * 上传图片
     *
     * @param url 图片URL
     * @return 图片ID
     */
    public static String uploadImage(WechatPayConfigDto configDto, String url) {
        if (configDto == null) {
            configDto = WechatPayConfigDto.getDefaultConfig();
        }
        // 校验入参
        if (url == null || url.trim().isEmpty()) {
            log.error("上传图片失败：URL参数为空");
            return "";
        }

        FileUploadService service = WechatConfig.getFileUploadService(configDto);

        try {
            // 获取图片字节数组
            byte[] bytes = UploadFileUtil.downloadImage(url);
            if (bytes.length == 0) {
                log.error("下载的图片内容为空，URL：{}", url);
                return "";
            }

            // 2. 计算SHA256
            String sha256Hex = WechatEncrypt.getFileBytesSha256(bytes);

            // 3. 构造元数据（从URL提取文件名，或自定义）
            JSONObject meta = new JSONObject();
            meta.put("sha256", sha256Hex);
            // 从URL提取文件名，若提取失败则使用默认名
            String fileName = UploadFileUtil.extractFileNameFromUrl(url);
            meta.put("filename", fileName);

            // 4. 上传图片到微信接口
            FileUploadResponse uploadResponse = service.uploadImage(
                    configDto.getDomain() + "/v3/merchant/media/upload",
                    meta.toJSONString(),
                    fileName,
                    bytes
            );

            return uploadResponse.getMediaId();
        } catch (MalformedMessageException e) {
            log.error("微信上传图片报错1，URL：{}", url);
        } catch (Exception e) {
            log.error("微信上传图片报错2，URL：{}", url);
        }
        return "";
    }

    /**
     * 构建进件参数
     *
     * @param reqDto 请求参数
     * @return 进件参数
     */
    private static WechatEntryReqDto buildEntryParams(WechatPayConfigDto configDto, AggregateMerchantDto reqDto) {
        WechatEntryReqDto entryParams = new WechatEntryReqDto();

        Config config = WechatConfig.getRsaConfig(configDto);
        PrivacyEncryptor encryptor = config.createEncryptor();

        entryParams.setBusinessCode(reqDto.getMerchantCode());

        MerchantBaseInfoDto baseInfo = reqDto.getMerchantBaseInfo();
        LegalPersonInfoDto legalPersonInfo = reqDto.getLegalPersonInfo();
        BusinessLicenceInfoDto businessLicenceInfo = reqDto.getBusinessLicenceInfo();
        StoreInfoDto storeInfo = reqDto.getStoreInfo();
        SettlementInfoDto settlementInfo = reqDto.getSettlementInfo();

        WechatEntryContactReqDto contactInfo = new WechatEntryContactReqDto();
        contactInfo.setContactType(baseInfo.getContactPersonType());
        // 默认都使用身份证 暂不支持其他证件
        contactInfo.setContactIdDocCopy("IDENTIFICATION_TYPE_IDCARD");
        if (PayCst.ContactPersonType.SUPER.equals(baseInfo.getContactPersonType())) {
            contactInfo.setContactName(encryptor.encrypt(baseInfo.getContactName()));
            contactInfo.setContactIdNumber(encryptor.encrypt(baseInfo.getContactPersonId()));
            contactInfo.setContactIdDocCopy(baseInfo.getContactIdCardFrontPic().getWechatId());
            contactInfo.setContactIdDocCopyBack(baseInfo.getContactIdCardBackPic().getWechatId());
            contactInfo.setContactPeriodBegin(baseInfo.getContactPersonIdStartDate());
            contactInfo.setContactPeriodEnd(PayCst.LONG_TERM_DATE.equals(baseInfo.getContactPersonIdEndDate()) ? "长期" : baseInfo.getContactPersonIdEndDate());
            contactInfo.setMobilePhone(encryptor.encrypt(baseInfo.getContactPhone()));
            contactInfo.setContactEmail(encryptor.encrypt(baseInfo.getContactEmail()));
        } else if (PayCst.ContactPersonType.LEGAL.equals(baseInfo.getContactPersonType())) {
            contactInfo.setContactName(encryptor.encrypt(legalPersonInfo.getLegalPersonName()));
            contactInfo.setContactIdNumber(encryptor.encrypt(legalPersonInfo.getLegalPersonId()));
            contactInfo.setContactIdDocCopy(legalPersonInfo.getIdCardFrontPic().getWechatId());
            contactInfo.setContactIdDocCopyBack(legalPersonInfo.getIdCardBackPic().getWechatId());
            contactInfo.setContactPeriodBegin(legalPersonInfo.getLegalIdPersonStartDate());
            contactInfo.setContactPeriodEnd(PayCst.LONG_TERM_DATE.equals(legalPersonInfo.getLegalPersonIdEndDate()) ? "长期" : legalPersonInfo.getLegalPersonIdEndDate());
            contactInfo.setMobilePhone(encryptor.encrypt(legalPersonInfo.getLegalPersonPhone()));
            contactInfo.setContactEmail(encryptor.encrypt(legalPersonInfo.getLegalPersonEmail()));
        } else {
            throw new CzgException("联系人类型错误");
        }
        entryParams.setContactInfo(contactInfo);

        WechatEntrySubjectReqDto subjectInfo = new WechatEntrySubjectReqDto();
        if ("0".equals(baseInfo.getUserType())) {
            subjectInfo.setSubjectType("SUBJECT_TYPE_INDIVIDUAL");
        } else if ("1".equals(baseInfo.getUserType())) {
            switch (baseInfo.getCompanyChildType()) {
                case "1" -> subjectInfo.setSubjectType("SUBJECT_TYPE_ENTERPRISE");
                case "2" -> subjectInfo.setSubjectType("SUBJECT_TYPE_INSTITUTIONS");
                case "3" -> subjectInfo.setSubjectType("SUBJECT_TYPE_GOVERNMENT");
                case "4" -> subjectInfo.setSubjectType("SUBJECT_TYPE_OTHERS");
                default -> throw new CzgException("主体类型错误");
            }
        } else {
            throw new CzgException("用户类型错误");
        }
        subjectInfo.setFinanceInstitution(false);

        WechatEntryLicenseReqDto licenseReqDto = new WechatEntryLicenseReqDto();
        licenseReqDto.setLicenseCopy(businessLicenceInfo.getLicensePic().getWechatId());
        licenseReqDto.setLicenseNumber(businessLicenceInfo.getLicenceNo());
        licenseReqDto.setMerchantName(businessLicenceInfo.getLicenceName());
        licenseReqDto.setLegalPerson(legalPersonInfo.getLegalPersonName());
        licenseReqDto.setLicenseAddress(businessLicenceInfo.getRegisteredAddress());
        licenseReqDto.setPeriodBegin(businessLicenceInfo.getLicenceStartDate());
        licenseReqDto.setPeriodEnd(PayCst.LONG_TERM_DATE.equals(businessLicenceInfo.getLicenceEndDate()) ? "长期" : businessLicenceInfo.getLicenceEndDate());
        subjectInfo.setBusinessLicenseInfo(licenseReqDto);
        WechatEntryIdentityReqDto identityInfo = new WechatEntryIdentityReqDto();
        identityInfo.setIdHolderType(PayCst.ContactPersonType.LEGAL);
        identityInfo.setIdDocType("IDENTIFICATION_TYPE_IDCARD");
        WechatEntryIdCardReqDto idCardInfo = new WechatEntryIdCardReqDto();
        idCardInfo.setIdCardCopy(legalPersonInfo.getIdCardFrontPic().getWechatId());
        idCardInfo.setIdCardNational(legalPersonInfo.getIdCardFrontPic().getWechatId());
        idCardInfo.setIdCardName(encryptor.encrypt(legalPersonInfo.getLegalPersonName()));
        idCardInfo.setIdCardNumber(encryptor.encrypt(legalPersonInfo.getLegalPersonId()));
        idCardInfo.setIdCardAddress(encryptor.encrypt(legalPersonInfo.getLegalAddress()));
        idCardInfo.setCardPeriodBegin(legalPersonInfo.getLegalIdPersonStartDate());
        idCardInfo.setCardPeriodEnd(legalPersonInfo.getLegalPersonIdEndDate());
        identityInfo.setIdCardInfo(idCardInfo);
        subjectInfo.setIdentityInfo(identityInfo);
        entryParams.setSubjectInfo(subjectInfo);

        WechatEntryBusinessReqDto businessReqInfo = new WechatEntryBusinessReqDto();
        businessReqInfo.setMerchantShortname(baseInfo.getShortName());
        businessReqInfo.setServicePhone(PayCst.ContactPersonType.LEGAL.equals(baseInfo.getContactPersonType()) ? legalPersonInfo.getLegalPersonPhone() : baseInfo.getContactPhone());
        WechatEntrySalesInfoReqDto salesInfo = new WechatEntrySalesInfoReqDto();
        salesInfo.setSalesScenesType(List.of("SALES_SCENES_STORE", "SALES_SCENES_MINI_PROGRAM"));
        WechatEntryStoreInfoReqDto bizStoreInfo = new WechatEntryStoreInfoReqDto();
        bizStoreInfo.setBizStoreName(baseInfo.getShortName());
        bizStoreInfo.setBizAddressCode(storeInfo.getMercAreaCode());
        bizStoreInfo.setBizStoreAddress(storeInfo.getBusinessAddress());
        bizStoreInfo.setStoreEntrancePic(List.of(storeInfo.getDoorPic().getWechatId()));
        bizStoreInfo.setIndoorPic(List.of(storeInfo.getInsidePic().getWechatId()));
        salesInfo.setBizStoreInfo(bizStoreInfo);
        WechatEntryMiniProgramReqDto miniProgramInfo = new WechatEntryMiniProgramReqDto();
        miniProgramInfo.setMiniProgramAppid("wxd88fffa983758a30");
        salesInfo.setMiniProgramInfo(miniProgramInfo);
        WechatEntryWebInfoReqDto webInfo = new WechatEntryWebInfoReqDto();
        webInfo.setDomain("https://invoice.sxczgkj.cn/pay/");
        salesInfo.setWebInfo(webInfo);
        businessReqInfo.setSalesInfo(salesInfo);
        entryParams.setBusinessInfo(businessReqInfo);

        WechatEntrySettleReqDto settlementReqInfo = new WechatEntrySettleReqDto();
        settlementReqInfo.setSettlementId("0".equals(baseInfo.getUserType()) ? "719" : "716");
        settlementReqInfo.setQualificationType("餐饮");
        settlementReqInfo.setActivitiesId("20191030111cff5b5e");
        settlementReqInfo.setActivitiesRate("0.38");
        entryParams.setSettlementInfo(settlementReqInfo);

        WechatEntryBankAccountReqDto bankAccountReqInfo = new WechatEntryBankAccountReqDto();
        bankAccountReqInfo.setBankAccountType("21".equals(settlementInfo.getSettlementCardType()) ? "BANK_ACCOUNT_TYPE_CORPORATE" : "BANK_ACCOUNT_TYPE_PERSONAL");
        bankAccountReqInfo.setAccountName(encryptor.encrypt(settlementInfo.getSettlementName()));
        bankAccountReqInfo.setBankAddressCode(settlementInfo.getOpenAccCityId());
        bankAccountReqInfo.setAccountBank(settlementInfo.getBankName());
        bankAccountReqInfo.setBankBranchId(settlementInfo.getBankBranchCode());
        bankAccountReqInfo.setBankName(settlementInfo.getBankBranchName());
        bankAccountReqInfo.setAccountNumber(encryptor.encrypt(settlementInfo.getSettlementCardNo()));
        entryParams.setBankAccountInfo(bankAccountReqInfo);

        return entryParams;
    }

    public static void main(String[] args) throws IOException {


//        queryMerchantEntryStatus(null, "20220106000000000001");

        int offset = 0;
        Integer limit = 100;
//        JSONObject resp = queryBankList(null, offset, limit);

//        queryProvinceList(null);
//        queryCityList(null, "28");
//        queryBankBranchList(null, "1000009547", "931", offset, limit);
//        queryBankBranchList(null, "1000009561", "29", offset, limit);
        queryBankBranchList(null, "1000005241", "29", offset, limit);

//        uploadImage(null, "https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/5/ec5bafd00f96466fb3efe545a058f08b.png");

//        queryProvinceList(dto);
//        queryCityList(dto, "28");


//        String string = uploadImage(dto, "https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png");
//        log.info("图片上传成功：{}", string);

//        Config config = WechatConfig.getRsaConfig(dto);
//        PrivacyEncryptor encryptor = config.createEncryptor();
//
//        WechatEntryReqDto reqDto = new WechatEntryReqDto()
//                .setBusinessCode("MER_20231025110010000010000000000001");
//
//        WechatEntryContactReqDto contactInfo = new WechatEntryContactReqDto()
//                .setContactType("LEGAL")
//                .setContactName(encryptor.encrypt("张三"))
//                .setContactIdType("IDCARD")
//                .setContactIdNumber(encryptor.encrypt("110101199001011234"))
//                .setContactIdDocCopy("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png")
//                .setContactIdDocCopyBack("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png")
//                .setContactPeriodBegin("2023-10-25")
//                .setContactPeriodEnd("2024-10-25")
//                .setMobilePhone(encryptor.encrypt("13888888888"))
//                .setContactEmail(encryptor.encrypt("123456@qq.com"));
//
//        reqDto.setContactInfo(contactInfo);
//
//        WechatEntrySubjectReqDto subjectInfo = new WechatEntrySubjectReqDto()
//                .setSubjectType("SUBJECT_TYPE_INDIVIDUAL");
//
//        WechatEntryLicenseReqDto licenseInfo = new WechatEntryLicenseReqDto()
//                .setLicenseCopy("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png")
//                .setLicenseNumber("110101199001011234")
//                .setMerchantName("张三商行")
//                .setLegalPerson(encryptor.encrypt("张三"))
//                .setLicenseAddress("北京")
//                .setPeriodBegin("2023-10-25")
//                .setPeriodEnd("2024-10-25");
//        subjectInfo.setBusinessLicenseInfo(licenseInfo);
//
//        WechatEntryIdentityReqDto identityInfo = new WechatEntryIdentityReqDto()
//                .setIdHolderType("LEGAL");
//        subjectInfo.setIdentityInfo(identityInfo);
//
//        reqDto.setSubjectInfo(subjectInfo);
//
//        WechatEntryBusinessReqDto businessInfo = new WechatEntryBusinessReqDto()
//                .setMerchantShortname("张三商行")
//                .setServicePhone("13888888888");
//        WechatEntrySalesInfoReqDto salesInfo = new WechatEntrySalesInfoReqDto()
//                .setSalesScenesType(List.of("SALES_SCENES_STORE"));
//        WechatEntryStoreInfoReqDto storeInfo = new WechatEntryStoreInfoReqDto()
//                .setBizStoreName("张三商行")
//                .setBizAddressCode("110101")
//                .setBizStoreAddress("北京")
//                .setStoreEntrancePic(List.of("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png"))
//                .setIndoorPic(List.of("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png"));
//        salesInfo.setBizStoreInfo(storeInfo);
//        businessInfo.setSalesInfo(salesInfo);
//
//        reqDto.setBusinessInfo(businessInfo);
//
//        WechatEntrySettleReqDto settleInfo = new WechatEntrySettleReqDto()
//                .setSettlementId("719")
//                .setQualificationType("IDCARD")
//                .setQualifications(List.of("110101199001011234"))
//                .setActivitiesId("20191030111cff5b5e");
//
//        reqDto.setSettlementInfo(settleInfo);
//
//        WechatEntryBankAccountReqDto bankAccountInfo = new WechatEntryBankAccountReqDto()
//                .setBankAccountType("BANK_ACCOUNT_TYPE_CORPORATE")
//                .setAccountBank("ICBC")
//                .setBankName("中国工商银行")
//                .setAccountName(encryptor.encrypt("张三"))
//                .setAccountNumber(encryptor.encrypt("110101199001011234"));
//
//        reqDto.setBankAccountInfo(bankAccountInfo);

//        entryMerchant(dto, reqDto);
    }
}
