package com.jeequan.jeepay.mch.ctrl.merchant;

import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.components.mq.vender.IMQSender;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.interfaces.IConfigContextQueryService;
import com.jeequan.jeepay.core.interfaces.paychannel.aliaqfbiz.IAliaqfApiService;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.DBApplicationConfig;
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
import com.jeequan.jeepay.core.model.params.aliaqf.AliaqfIsvParams;
import com.jeequan.jeepay.core.model.params.aliaqf.AliaqfIsvsubMchParams;
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
import com.jeequan.jeepay.db.entity.MchAppEntity;
import com.jeequan.jeepay.db.entity.MchInfo;
import com.jeequan.jeepay.db.entity.PayInterfaceConfig;
import com.jeequan.jeepay.db.entity.PayInterfaceDefine;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 商户支付接口配置类
 *
 * @author zhuxiao
 *
 * @date 2021-04-27 15:50
 */
@Slf4j
@RestController
@RequestMapping("/api/mch/payConfigs")
public class MchPayInterfaceConfigController extends CommonCtrl {

    @Autowired
    private PayInterfaceDefineService payInterfaceDefineService;
    @Autowired
    private PayInterfaceConfigService payInterfaceConfigService;
    @Autowired
    private MchInfoService mchInfoService;
    @Autowired
    private MchAppService mchAppService;
    @Autowired
    private SysConfigService sysConfigService;
    @Autowired
    private IMQSender mqSender;
    @Autowired
    private IConfigContextQueryService configContextQueryService;

    /**
     * @Author: ZhuXiao
     * @Description: 查询商户支付接口配置列表
     * @Date: 10:51 2021/5/13
     */
    @GetMapping
    public ApiRes list() {
        MchInfo mchInfo = mchInfoService.getById(getCurrentUser().getSysUser().getBelongInfoId());
        List<PayInterfaceDefine> list = payInterfaceConfigService.selectAllPayIfConfigListByAppId(getValStringRequired("appId"));

        for (PayInterfaceDefine define : list) {
            define.addExt("mchParams", mchInfo.getType() == CS.MCH_TYPE_NORMAL ? define.getNormalMchParams() : define.getIsvsubMchParams());
            define.setNormalMchParams(null);
            define.setIsvsubMchParams(null);
        }
        return ApiRes.ok(list);
    }


    /**
     * 查询支付宝商户授权URL
     **/
    @GetMapping("/alipayIsvsubMchAuthUrls/{mchAppId}/{isvNo}")
    public ApiRes queryAlipayIsvsubMchAuthUrl(@PathVariable("mchAppId") String mchAppId,
                                              @PathVariable("isvNo") String isvNo) {

        MchAppEntity mchAppEntity = mchAppService.getById(mchAppId);

        if (mchAppEntity == null || !mchAppEntity.getMchNo().equals(getCurrentMchNo())) {
            return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
        }

        MchInfo mchInfo = mchInfoService.getById(mchAppEntity.getMchNo());
        DBApplicationConfig dbApplicationConfig = sysConfigService.getDBApplicationConfig();
        String authUrl = dbApplicationConfig.genAlipayIsvsubMchAuthUrl(isvNo, mchAppId);
        String authQrImgUrl = dbApplicationConfig.genScanImgUrl(authUrl);

        JSONObject result = new JSONObject();
        result.put("authUrl", authUrl);
        result.put("authQrImgUrl", authQrImgUrl);
        return ApiRes.ok(result);
    }


    /**
     * 查询当前应用支持的支付接口
     */
    @PreAuthorize("hasAuthority( 'ENT_DIVISION_RECEIVER_ADD' )")
    @RequestMapping(value = "ifCodes/{appId}", method = RequestMethod.GET)
    public ApiRes getIfCodeByAppId(@PathVariable("appId") String appId) {

        if (mchAppService.lambdaQuery().eq(MchAppEntity::getAppId, appId).eq(MchAppEntity::getMchNo, getCurrentMchNo()).count() <= 0) {
            throw new BizException("商户应用不存在");
        }

        Set<String> result = new HashSet<>();

        payInterfaceConfigService.list(PayInterfaceConfig.gw().select(PayInterfaceConfig::getIfCode).eq(PayInterfaceConfig::getState, CS.PUB_USABLE).eq(PayInterfaceConfig::getInfoId, appId).eq(PayInterfaceConfig::getInfoType, CS.SYS_ROLE_TYPE.MCH_APP)).forEach(r -> result.add(r.getIfCode()));

        if (result.isEmpty()) {
            return ApiRes.ok(new ArrayList<>());
        }

        return ApiRes.ok(payInterfaceDefineService.list(PayInterfaceDefine.gw().select(PayInterfaceDefine::getIfCode, PayInterfaceDefine::getIfName, PayInterfaceDefine::getIcon, PayInterfaceDefine::getBgColor).in(PayInterfaceDefine::getIfCode, result)));
    }

    /**
     * 支付宝安全发签约页面
     **/
    @PreAuthorize("hasAuthority( 'AGREEMENT_PAGE_SIGN' )")
    @GetMapping("/alipayAgreementPageSign/{mchAppId}/{isvNo}")
    public ApiRes alipayAgreementPageSign(@PathVariable("mchAppId") String mchAppId, @PathVariable("isvNo") String isvNo) {

        MchAppEntity mchAppEntity = mchAppService.getById(mchAppId);
        // 权限判断
        if (!mchAppEntity.getMchNo().equals(getCurrentMchNo())) {
            return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
        }

        AliaqfIsvParams aliaqfIsvParams = getIsvParams(mchAppEntity.getMchNo(), isvNo);

        IAliaqfApiService aliaqfApiService = SpringBeansUtil.getBean(CS.IF_CODE.ALIAQF + "ApiService", IAliaqfApiService.class);

        // 获取签约页面
        String jumpUrl = aliaqfApiService.userAgreementPageSign(aliaqfIsvParams, mchAppId);

        return ApiRes.ok(jumpUrl);
    }

    /**
     * 查询支付宝安全发签约结果
     */
    @PreAuthorize("hasAnyAuthority( 'USER_AGREEMENT_PAGE_SIGN', 'AGREEMENT_PAGE_SIGN' )")
    @GetMapping("/queryUserAgreementPageSign/{mchAppId}/{isvNo}")
    public ApiRes queryUserAgreementPageSign(@PathVariable("mchAppId") String mchAppId,
                                             @PathVariable("isvNo") String isvNo) {

        MchAppEntity mchAppEntity = mchAppService.getById(mchAppId);
        // 权限判断
        if (!mchAppEntity.getMchNo().equals(getCurrentMchNo())) {
            return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
        }

        MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
        if (MchInfo.TYPE_ISVSUB != mchInfo.getType()) {
            throw new BizException("仅支持特约商户");
        }

        AliaqfIsvParams ALIAQFIsvParams = (AliaqfIsvParams) configContextQueryService.queryIsvParams(isvNo, CS.IF_CODE.ALIAQF);
        if (ALIAQFIsvParams == null) {
            JSONObject isvReturnJson = new JSONObject();
            isvReturnJson.put("isvConfigIsOpen", "hide");
            log.info("{}当前服务商未配置安全发参数", isvNo);
            return ApiRes.ok(isvReturnJson);
        }

        // 商户应用配置是否开启；如果当前应用配置
        PayInterfaceConfig infoIdAndIfCode = payInterfaceConfigService.getByInfoIdAndIfCode(CS.SYS_ROLE_TYPE.MCH_APP, mchAppEntity.getAppId(), CS.IF_CODE.ALIAQF);
        if (infoIdAndIfCode == null || infoIdAndIfCode.getState() != CS.YES) {
            JSONObject buttonJson = new JSONObject();
            buttonJson.put("isShowButton", "hide");
            log.info("{}当前商户应用未开启安全发配置", mchAppEntity.getAppId());
            return ApiRes.ok(buttonJson);
        }

        IAliaqfApiService aliaqfApiService = SpringBeansUtil.getBean(CS.IF_CODE.ALIAQF + "ApiService", IAliaqfApiService.class);

        // 1.查询签约结果
        String agreementNo = aliaqfApiService.queryUserAgreementPageSign(ALIAQFIsvParams, mchAppId);

        String accountBookId = "";
        if (StringUtils.isNotEmpty(agreementNo)) {
            // 2.资金记账本开通
            accountBookId = aliaqfApiService.fundAccountbookCreate(ALIAQFIsvParams, mchAppId, mchAppEntity.getMchNo(), agreementNo);
        }

        // 更新保存该应用配置
        AliaqfIsvsubMchParams mchParams = new AliaqfIsvsubMchParams();
        mchParams.setAgreementNo(agreementNo);
        mchParams.setAccountBookId(accountBookId);

        // 配置信息为空时，不操作保存更新
        if (StringUtils.isNotEmpty(agreementNo) || StringUtils.isNotEmpty(accountBookId)) {
            PayInterfaceConfig config = payInterfaceConfigService.getByInfoIdAndIfCode(CS.SYS_ROLE_TYPE.MCH_APP, mchAppId, CS.IF_CODE.ALIAQF);
            if (config != null) {

                // 配置参数不为空不做更新处理
                AliaqfIsvsubMchParams dbMchParams = JSONObject.parseObject(config.getIfParams(), AliaqfIsvsubMchParams.class);
                // 签约码、记账本ID不为空时直接返回数据
                if (dbMchParams != null && StringUtils.isNotEmpty(dbMchParams.getAgreementNo()) && StringUtils.isNotEmpty(dbMchParams.getAccountBookId())) {
                    return ApiRes.ok(dbMchParams);
                }

                config.setIfParams(JSONObject.toJSONString(mchParams));

            } else {
                config = new PayInterfaceConfig();
                // 账号类型 商户应用类型
                config.setInfoType(CS.SYS_ROLE_TYPE.MCH_APP);
                // 商户appId
                config.setInfoId(mchAppId);
                // 支付接口代码
                config.setIfCode(CS.IF_CODE.ALIAQF);
                // 接口配置参数
                config.setIfParams(JSONObject.toJSONString(mchParams));
            }
            boolean result = payInterfaceConfigService.saveOrUpdate(config);
            if (!result) {
                return ApiRes.fail(ApiCodeEnum.SYSTEM_ERROR, "请联系开发人员");
            }
        }

        return ApiRes.ok(mchParams);
    }

    /**
     * 记账本信息查询
     **/
    @PreAuthorize("hasAnyAuthority( 'FUND_ACCOUNTBOOK_QUERY', 'AGREEMENT_PAGE_SIGN' )")
    @GetMapping("/fundAccountbookQuery/{mchAppId}")
    public ApiRes fundAccountbookQuery(@PathVariable String mchAppId) {

        MchAppEntity mchAppEntity = mchAppService.getById(mchAppId);
        // 权限判断
        if (!mchAppEntity.getMchNo().equals(getCurrentMchNo())) {
            return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
        }

        IAliaqfApiService aliaqfApiService = SpringBeansUtil.getBean(CS.IF_CODE.ALIAQF + "ApiService", IAliaqfApiService.class);
        if (aliaqfApiService == null) {
            throw new BizException("无支付宝安全发接口");
        }

        MchAppConfigContext mchAppConfigContext = configContextQueryService.queryMchInfoAndAppInfoV2(mchAppEntity.getMchNo(), mchAppEntity.getAppId(),null);

        // 查询记账本详情
        JSONObject accountBookInfo = aliaqfApiService.fundAccountbookQuery(mchAppConfigContext);
        return ApiRes.ok(accountBookInfo);
    }

    /**
     * 资金转账页面
     **/
    @PreAuthorize("hasAnyAuthority( 'FUND_TRANS_PAGE', 'AGREEMENT_PAGE_SIGN' )")
    @PostMapping("/fundTransPage/{mchAppId}/｛isvNo｝")
    public ApiRes fundTransPage(@PathVariable("mchAppId") String mchAppId,
                                @PathVariable("isvNo") String isvNo) {

        MchAppEntity mchAppEntity = mchAppService.getById(mchAppId);

        // 充值金额
        Long transAmount = getAmountL("transAmount");

        // 权限判断
        if (!mchAppEntity.getMchNo().equals(getCurrentMchNo())) {
            return ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR);
        }

        AliaqfIsvParams aliaqfIsvParams = getIsvParams(mchAppEntity.getMchNo(), isvNo);

        IAliaqfApiService aliaqfApiService = SpringBeansUtil.getBean(CS.IF_CODE.ALIAQF + "ApiService", IAliaqfApiService.class);

        if (aliaqfApiService == null) {
            throw new BizException("无支付宝安全发接口");
        }

        // 资金转账页面
        String transPage = aliaqfApiService.fundTransPage(aliaqfIsvParams, mchAppId, getCurrentMchNo(), transAmount);
        return ApiRes.ok(transPage);
    }

    /**
     * @author: xiaoyu
     * @date: 2023/4/5 11:34
     * @describe: 获取支付宝安全发服务商参数
     */
    private AliaqfIsvParams getIsvParams(String mchNo, String isvNo) {
        MchInfo mchInfo = mchInfoService.getById(mchNo);
        if (MchInfo.TYPE_ISVSUB != mchInfo.getType()) {
            throw new BizException("仅支持特约商户");
        }

        AliaqfIsvParams isvParams = (AliaqfIsvParams) configContextQueryService.queryIsvParams(isvNo, CS.IF_CODE.ALIAQF);
        if (isvParams == null) {
            throw new BizException("服务商未配置参数，请联系平台处理！");
        }
        return isvParams;
    }

}
