package com.hzs.member.account.service.impl;


import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzs.common.core.constant.EnumsPrefixConstants;
import com.hzs.common.core.enums.*;
import com.hzs.common.core.utils.CommonUtil;
import com.hzs.common.core.utils.StringUtils;
import com.hzs.common.domain.member.account.*;
import com.hzs.common.domain.system.config.BdAccount;
import com.hzs.member.account.dto.CuMemberBatchRechargeDetailParam;
import com.hzs.member.account.dto.CuMemberBatchRechargeParam;
import com.hzs.member.account.dto.CuMemberRechargeAccountParam;
import com.hzs.member.account.dto.CuMemberRechargeParam;
import com.hzs.member.account.mapper.CuMemberRechargeApplicationMapper;
import com.hzs.member.account.mapper.CuMemberRechargeDetailMapper;
import com.hzs.member.account.mapper.CuMemberRechargeMapper;
import com.hzs.member.account.service.*;
import com.hzs.member.account.vo.CuMemberRechargeApplicationVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * <p>
 * 会员充值申请 服务实现类
 * </p>
 *
 * @author hzs
 * @since 2024-02-18
 */
@Service
public class CuMemberRechargeApplicationServiceImpl extends ServiceImpl<CuMemberRechargeApplicationMapper, CuMemberRechargeApplication> implements ICuMemberRechargeApplicationService {


    @Autowired
    private ICuMemberBaseService memberBaseService;


    @Autowired
    private ICuMemberAccountService cuMemberAccountService;

    @Autowired
    private ICuMemberTradeService cuMemberTradeService;

    @Autowired
    private CuMemberRechargeDetailMapper cuMemberRechargeDetailMapper;

    @Autowired
    private ICuMemberRechargeService cuMemberRechargeService;

    @Override
    public Boolean saveApplication(CuMemberRechargeApplicationVO rechargeApplicationVO) {
        CuMemberRechargeApplication cuMemberRechargeApplication = BeanUtil.copyProperties(rechargeApplicationVO, CuMemberRechargeApplication.class);
        cuMemberRechargeApplication.setApplicationStatus(EPersonalServiceStatus.APPLIED_FOR.getValue());
        return this.save(cuMemberRechargeApplication);
    }

    @Override
    public Object[] findRechargeApplicationList(CuMemberRechargeApplicationVO rechargeApplicationVO) {
        List<CuMemberRechargeApplicationExt> rechargeApplicationList = baseMapper.findRechargeApplicationList(rechargeApplicationVO);
        List<CuMemberRechargeApplicationVO> rechargeApplicationVOList = BeanUtil.copyToList(rechargeApplicationList, CuMemberRechargeApplicationVO.class);
        Object[] objects = new Object[]{rechargeApplicationList, rechargeApplicationVOList};
        return objects;
    }

    @Override
    public Boolean updateRejectionStatement(CuMemberRechargeApplicationVO rechargeApplicationVO) {
        return updateRechargeApplication(rechargeApplicationVO, EPersonalServiceStatus.REJECTED);
    }

    @Override
    public CuMemberRechargeApplication selectApplicationById(Long pkId) {
        return baseMapper.selectById(pkId);
    }

    private Boolean updateRechargeApplication(CuMemberRechargeApplicationVO rechargeApplicationVO, EPersonalServiceStatus ePersonalServiceStatus) {
        Long pkMember = rechargeApplicationVO.getPkMember();
        UpdateWrapper<CuMemberRechargeApplication> updateWrapper = new UpdateWrapper<>();
        String rejectionStatement = rechargeApplicationVO.getRejectionStatement();
        if (StringUtils.isNotEmpty(rejectionStatement)) {
            updateWrapper.set("REJECTION_STATEMENT", rejectionStatement);
        }
        updateWrapper.set("APPLICATION_STATUS", ePersonalServiceStatus.getValue())
                .set("APPROVER", pkMember)
                .set("APPROVE_TIME", new Date())
                .set("PK_MODIFIED", pkMember)
                .set("MODIFIED_TIME", new Date())
                .eq("PK_ID", rechargeApplicationVO.getPkId());
        return update(updateWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean applicationAgree(Long pkId, Long pkMember, CuMemberRechargeApplication rechargeApplication) {
        //充值信息
        CuMemberRecharge cuMemberRecharge = packageCuMemberRecharge(rechargeApplication, pkMember);
        //充值详情
        CuMemberRechargeDetail cuMemberRechargeDetail = packageCuMemberRechargeDetail(cuMemberRecharge);
        //交易流水
        CuMemberTrade cuMemberTrade = getCuMemberTrade(cuMemberRecharge);
        if (null != pkId) {
            //更新充值申请信息
            CuMemberRechargeApplicationVO rechargeApplicationVO = CuMemberRechargeApplicationVO.builder()
                    .pkMember(pkMember).pkId(pkId).build();
            updateRechargeApplication(rechargeApplicationVO, EPersonalServiceStatus.PASSED);
        }
        //批量插入充值表
        cuMemberRechargeService.save(cuMemberRecharge);
        //批量插入充值详情表
        cuMemberRechargeDetailMapper.batchSaveMemberRechargeDetail(Collections.singletonList(cuMemberRechargeDetail));

        //批量插入流水表
        cuMemberTradeService.batchSaveTradeByMemberCode(Collections.singletonList(cuMemberTrade));
        //批理更新余额
        return cuMemberAccountService.updateBatchMemberAccountByPkmember(cuMemberRecharge.getBatch(), pkMember, ETransferType.TRANSFER_IN.getValue());
    }


    /**
     * 拼装充值信息
     *
     * @param rechargeApplication 充值申请信息
     * @param pkMember            会员ID
     * @return CuMemberRecharge
     */
    private CuMemberRecharge packageCuMemberRecharge(CuMemberRechargeApplication rechargeApplication, Long pkMember) {
        Integer pkCountry = rechargeApplication.getPkCountry();
        //充值单号
        String rechargeCode = CommonUtil.createSerialNumber(EOrderPrefix.RECHARGE_CODE.getValue());
        CuMemberRecharge memberRecharge = CuMemberRecharge.builder().pkMember(rechargeApplication.getPkMember())
                .rechargeAmount(rechargeApplication.getRemittanceAmount())
                .pkAccount(getPkAccount(pkCountry)).rechargeCode(rechargeCode)
                .rechargeType(String.valueOf(EPaymentType.BANK_CARD.getValue()))
                .rechargeMethod(ERechargeMethod.ADD.getValue())
                .remarks(rechargeApplication.getRemittanceInstructions())
                .batch(rechargeCode)
                .build();
        memberRecharge.setApprover(pkMember);
        memberRecharge.setApproveTime(new Date());
        memberRecharge.setApproveState(EApproveRechargeStatus.AGREE.getValue());
        memberRecharge.setPkCountry(pkCountry);
        memberRecharge.setPkCreator(pkMember);
        memberRecharge.setCreationTime(new Date());
        memberRecharge.setPkRate(memberBaseService.getCurrency(pkCountry).getPkId());
        return memberRecharge;
    }


    /**
     * 拼装充值信息详情
     *
     * @param memberRecharge 充值信息
     * @return CuMemberRechargeDetail
     */
    private CuMemberRechargeDetail packageCuMemberRechargeDetail(CuMemberRecharge memberRecharge) {
        BigDecimal rechargeAmount = memberRecharge.getRechargeAmount();
        //余额
        CuMemberAccount cuMemberAccount = cuMemberAccountService.queryCuMemberAccountByPkMember(memberRecharge.getPkMember());
        BigDecimal balance = cuMemberAccount.getAccount1();
        CuMemberRechargeDetail detail = CuMemberRechargeDetail.builder()
                .rechargeCode(memberRecharge.getRechargeCode()).paymentMethod(Integer.parseInt(memberRecharge.getRechargeType()))
                .paymentAmount(rechargeAmount)
                .paymentBeforeBalance(balance)
                .paymentBalance(balance.add(rechargeAmount))
                .build();
        detail.setPkCreator(memberRecharge.getPkCreator());
        return detail;
    }


    /**
     * 构造交易明细
     *
     * @param cuMemberRecharge 充值信息
     * @return CuMemberTrade
     */
    private CuMemberTrade getCuMemberTrade(CuMemberRecharge cuMemberRecharge) {
        Long pkMember = cuMemberRecharge.getPkMember();
        int pkAccount = cuMemberRecharge.getPkAccount();
        BdAccount account = memberBaseService.getAccount(pkAccount);
        //充值金额
        BigDecimal tradeAmount = cuMemberRecharge.getRechargeAmount();
        //查询余额
        BigDecimal balance = cuMemberAccountService.selectBalanceByMemberCode(pkMember, account.getFieldValue());
        CuMemberTrade memberTrade = CuMemberTrade.builder().pkMember(pkMember)
                .tradeCode(cuMemberRecharge.getRechargeCode())
                .pkAccount(pkAccount)
                .tradeType(ETradeType.OFF_LINE_RECHARGE.getValue())
                .tradeClassify(ETradeClassify.RECHARGE.getValue())
                .pkRate(cuMemberRecharge.getPkRate())
                .tradeAmount(tradeAmount)
                .tradeBeforeBalance(balance)
                .tradeBalance(balance.add(tradeAmount))
                .sourceCode(cuMemberRecharge.getBatch())
                .tradeStatue(ETradeStatus.TAKE_EFFECT.getValue())
                .remarks(cuMemberRecharge.getRemarks())
                .build();
        memberTrade.setPkCreator(cuMemberRecharge.getPkCreator());
        memberTrade.setPkCountry(cuMemberRecharge.getPkCountry());
        return memberTrade;
    }

    /**
     * 根据国家币种值查询ID
     *
     * @param pkCountry 国家ID
     * @return Integer
     */
    private Integer getPkAccount(Integer pkCountry) {
        List<BdAccount> bdAccountList = memberBaseService.getAccountByCountryId(pkCountry);
        BdAccount account = bdAccountList.stream().filter(bdAccount -> bdAccount.getFieldValue().equals(EAccount.CONSUME.getValue())).findFirst().orElse(null);
        return account.getPkId();

    }

}
