package com.jsowell.adapay.service;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.huifu.adapay.core.exception.BaseAdaPayException;
import com.huifu.adapay.model.Member;
import com.huifu.adapay.model.SettleAccount;
import com.jsowell.adapay.dto.AdapayMemberInfoDTO;
import com.jsowell.adapay.dto.UpdateAccountConfigDTO;
import com.jsowell.adapay.response.QueryMemberResponse;
import com.jsowell.adapay.vo.AdapayAccountBalanceVO;
import com.jsowell.adapay.vo.AdapayMemberInfoVO;
import com.jsowell.adapay.vo.AdapaySettleAccountVO;
import com.jsowell.common.exception.BusinessException;
import com.jsowell.common.util.StringUtils;
import com.jsowell.common.util.id.IdUtils;
import com.jsowell.pile.domain.AdapayMemberAccount;
import com.jsowell.pile.service.IAdapayMemberAccountService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Map;

@Slf4j
@Service
public class AdapayMemberService {

    @Value("${adapay.appId}")
    private String ADAPAY_APP_ID;

    @Autowired
    private IAdapayMemberAccountService adapayMemberAccountService;

    /**
     * 创建汇付会员
     *
     * @param dto
     * @throws Exception
     */
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public void createMember(AdapayMemberInfoDTO dto) throws Exception {
        AdapayMemberAccount adapayMemberAccount = adapayMemberAccountService.selectByMerchantId(dto.getMerchantId());
        if (adapayMemberAccount != null) {
            return;
        }
        log.info("=======execute CreateMember begin=======");
        Map<String, Object> memberParams = Maps.newHashMap();
        String adapayMemberId = "AM" + IdUtils.getMemberId();
        memberParams.put("member_id", adapayMemberId);
        memberParams.put("app_id", ADAPAY_APP_ID);
        memberParams.put("location", dto.getLocation());
        memberParams.put("email", dto.getEmail());
        memberParams.put("gender", dto.getGender());
        memberParams.put("nickname", dto.getNickname());
        log.info("创建用户，请求参数：" + JSON.toJSONString(memberParams));
        Map<String, Object> member = Member.create(memberParams);
        log.info("创建用户，返回参数：" + JSON.toJSONString(member));
        log.info("=======execute CreateMember end=======");

        if (member == null || StringUtils.equals((String) member.get("status"), "failed")) {
            String errorMsg = member == null ? "创建汇付用户失败" : (String) member.get("error_msg");
            throw new BusinessException("00500001", errorMsg);
        }

        // 创建结算账户
        Map<String, Object> accountInfo = Maps.newHashMap();
        // 银行卡号
        accountInfo.put("card_id", dto.getCardId());
        // 银行卡对应的户名
        accountInfo.put("card_name", dto.getCardName());
        // 证件号，银行账户类型为对私时，必填
        if (StringUtils.isNotBlank(dto.getCertId())) {
            accountInfo.put("cert_id", dto.getCertId());
        }
        // 证件类型，仅支持：00-身份证，银行账户类型为对私时，必填
        accountInfo.put("cert_type", "00");
        // 手机号
        accountInfo.put("tel_no", dto.getTelNo());
        // 银行编码，详见附录 银行代码，银行账户类型对公时，必填
        if (StringUtils.isNotBlank(dto.getBankCode())) {
            accountInfo.put("bank_code", dto.getBankCode());
        }
        // 银行账户类型：1-对公；2-对私
        accountInfo.put("bank_acct_type", dto.getBankAcctType());
        // 银行账户开户银行所在省份编码 （省市编码），银行账户类型为对公时，必填
        if (StringUtils.isNotBlank(dto.getProvCode())) {
            accountInfo.put("prov_code", dto.getProvCode());
        }
        // 银行账户开户银行所在地区编码（省市编码），银行账户类型为对公时，必填
        if (StringUtils.isNotBlank(dto.getAreaCode())) {
            accountInfo.put("area_code", dto.getAreaCode());
        }

        Map<String, Object> settleCountParams = Maps.newHashMap();
        settleCountParams.put("member_id", adapayMemberId);
        settleCountParams.put("app_id", ADAPAY_APP_ID);
        // channel String Y 目前仅支持：bank_account（银行卡）
        settleCountParams.put("channel", "bank_account");
        settleCountParams.put("account_info", accountInfo);
        log.info("创建汇付结算账户param:{}", settleCountParams);
        Map<String, Object> settleCount = SettleAccount.create(settleCountParams);
        log.info("创建汇付结算账户result:{}", settleCount);

        if (settleCount == null || StringUtils.equals((String) settleCount.get("status"), "failed")) {
            String errorMsg = settleCount == null ? "创建汇付结算账户失败" : (String) settleCount.get("error_msg");
            throw new BusinessException("00500001", errorMsg);
        }

        String settleAccountId = (String) settleCount.get("id");
        // 保存到数据库
        adapayMemberAccount = new AdapayMemberAccount();
        adapayMemberAccount.setMerchantId(dto.getMerchantId());
        adapayMemberAccount.setAdapayMemberId(adapayMemberId);
        adapayMemberAccount.setSettleAccountId(settleAccountId);
        adapayMemberAccountService.insertAdapayMemberAccount(adapayMemberAccount);
    }

    /**
     * 查询汇付会员信息
     *
     * @param merchantId
     * @return
     */
    public Map<String, Object> selectAdapayMember(String merchantId) throws BaseAdaPayException {
        Map<String, Object> map = Maps.newHashMap();
        AdapayMemberAccount adapayMemberAccount = adapayMemberAccountService.selectByMerchantId(merchantId);
        if (adapayMemberAccount == null) {
            return null;
        }

        String adapayMemberId = adapayMemberAccount.getAdapayMemberId();
        String settleAccountId = adapayMemberAccount.getSettleAccountId();

        AdapayMemberInfoVO adapayMemberInfoVO = queryAdapayMemberInfo(adapayMemberId);
        if (adapayMemberInfoVO != null) {
            adapayMemberInfoVO.setMerchantId(merchantId);
        }
        AdapaySettleAccountVO adapaySettleAccountVO = queryAdapaySettleAccount(adapayMemberId, settleAccountId);
        if (adapaySettleAccountVO != null) {
            adapaySettleAccountVO.setMerchantId(merchantId);
        }
        map.put("adapayMember", adapayMemberInfoVO);
        map.put("settleAccountList", Lists.newArrayList(adapaySettleAccountVO));
        return map;
    }


    /**
     * 查询汇付会员信息
     */
    public AdapayMemberInfoVO queryAdapayMemberInfo(String adapayMemberId) throws BaseAdaPayException {
        if (StringUtils.isBlank(adapayMemberId)) {
            return null;
        }
        Map<String, Object> memberParams = Maps.newHashMap();
        memberParams.put("member_id", adapayMemberId);
        memberParams.put("app_id", ADAPAY_APP_ID);
        log.info("查询用户，请求参数：{}", JSON.toJSONString(memberParams));
        Map<String, Object> member = Member.query(memberParams);
        log.info("查询用户，返回参数：{}", JSON.toJSONString(member));

        if (member == null || member.isEmpty() || !"succeeded".equals(member.get("status"))) {
            return null;
        }

        QueryMemberResponse queryMemberResponse = JSON.parseObject(JSON.toJSONString(member), QueryMemberResponse.class);
        AdapayMemberInfoVO resultVO = AdapayMemberInfoVO.builder()
                .nickname(queryMemberResponse.getNickname())
                .gender(queryMemberResponse.getGender())
                .email(queryMemberResponse.getEmail())
                .location(queryMemberResponse.getLocation())
                .build();
        return resultVO;
    }

    /**
     * 查询汇付结算账户信息
     */
    public AdapaySettleAccountVO queryAdapaySettleAccount(String adapayMemberId, String settleAccountId) throws BaseAdaPayException {
        if (StringUtils.isBlank(adapayMemberId) || StringUtils.isBlank(settleAccountId)) {
            return null;
        }

        Map<String, Object> settleCountParams = Maps.newHashMap();
        settleCountParams.put("settle_account_id", settleAccountId);
        settleCountParams.put("member_id", adapayMemberId);
        settleCountParams.put("app_id", ADAPAY_APP_ID);

        log.info("查询汇付结算账户信息param:{}", JSON.toJSONString(settleCountParams));
        Map<String, Object> settleAccount = SettleAccount.query(settleCountParams);
        log.info("查询汇付结算账户信息result:{}", JSON.toJSONString(settleAccount));

        if (settleAccount == null || settleAccount.isEmpty() || !"succeeded".equals(settleAccount.get("status"))) {
            return null;
        }

        QueryMemberResponse.SettleAccount settleAccountInfo = JSON.parseObject(JSON.toJSONString(settleAccount), QueryMemberResponse.SettleAccount.class);
        QueryMemberResponse.AccountInfo accountInfo = settleAccountInfo.getAccount_info();

        AdapaySettleAccountVO resultVO = AdapaySettleAccountVO.builder()
                .adapayMemberId(settleAccountInfo.getMember_id())
                .settleAccountId(settleAccountInfo.getId())
                .cardId(accountInfo.getCard_id())
                .cardName(accountInfo.getCard_name())
                .certId(accountInfo.getCert_id())
                .certType(accountInfo.getCert_type())
                .telNo(accountInfo.getTel_no())
                .bankName(accountInfo.getBank_name())
                .bankCode(accountInfo.getBank_code())
                .bankAcctType(accountInfo.getBank_acct_type())
                .provCode(accountInfo.getProv_code())
                .areaCode(accountInfo.getArea_code())
                .build();
        return resultVO;
    }

    /**
     * 查询汇付会员账户余额
     */
    public AdapayAccountBalanceVO queryAdapayAccountBalance(String merchantId) throws BaseAdaPayException {
        AdapayAccountBalanceVO vo = AdapayAccountBalanceVO.builder().build();
        // 通过merchantId 查询出汇付会员id 和 结算账户id，用来查询余额
        AdapayMemberAccount adapayMemberAccount = adapayMemberAccountService.selectByMerchantId(merchantId);
        if (adapayMemberAccount == null) {
            return vo;
        }
        String settle_account_id = adapayMemberAccount.getSettleAccountId();
        String member_id = adapayMemberAccount.getAdapayMemberId();
        Map<String, Object> queryParams = Maps.newHashMap();
        queryParams.put("settle_account_id", settle_account_id);
        queryParams.put("member_id", member_id);
        queryParams.put("app_id", ADAPAY_APP_ID);
        Map<String, Object> settleCount = SettleAccount.balance(queryParams);
        if (settleCount == null || settleCount.isEmpty() || !"succeeded".equals(settleCount.get("status"))) {
            return vo;
        }
        vo.setFrzBalance(new BigDecimal((String) settleCount.get("frz_balance")));
        vo.setAcctBalance(new BigDecimal((String) settleCount.get("acct_balance")));
        vo.setAvlBalance(new BigDecimal((String) settleCount.get("avl_balance")));
        vo.setLastAvlBalance(new BigDecimal((String) settleCount.get("last_avl_balance")));
        return vo;
    }

    public void updateSettleAccountConfig(UpdateAccountConfigDTO dto) throws BaseAdaPayException {
        // 通过merchantId 查询出汇付会员id 和 结算账户id，用来查询余额
        AdapayMemberAccount adapayMemberAccount = adapayMemberAccountService.selectByMerchantId(dto.getMerchantId());
        if (adapayMemberAccount == null) {
            return;
        }
        // 修改账户配置
        Map<String, Object> params = Maps.newHashMap();
        params.put("app_id", ADAPAY_APP_ID);
        params.put("member_id", adapayMemberAccount.getAdapayMemberId());
        params.put("settle_account_id", adapayMemberAccount.getSettleAccountId());
        if (StringUtils.isNotBlank(dto.getMinAmt())) {
            params.put("min_amt", dto.getMinAmt());
        }
        if (StringUtils.isNotBlank(dto.getRemainedAmt())) {
            params.put("remained_amt", dto.getRemainedAmt());
        }
        if (StringUtils.isNotBlank(dto.getChannelRemark())) {
            params.put("channel_remark", dto.getChannelRemark());
        }
        Map<String, Object> settleCount = SettleAccount.update(params);
    }
}
