package cn.newfeifan.mall.module.distri.service.applicationforwithdrawalchannel;

import cn.newfeifan.mall.framework.common.exception.ErrorCode;
import cn.newfeifan.mall.module.distri.constant.DistriConstants;
import cn.newfeifan.mall.module.distri.controller.admin.applicationforwithdrawal.vo.ApplicationForWithdrawalSaveReqVO;
import cn.newfeifan.mall.module.distri.controller.admin.ptdailywithdrawal.vo.PtDailyWithdrawalSaveReqVO;
import cn.newfeifan.mall.module.distri.dal.dataobject.applicationforwithdrawal.ApplicationForWithdrawalDO;
import cn.newfeifan.mall.module.distri.dal.dataobject.ptdailywithdrawal.PtDailyWithdrawalDO;
import cn.newfeifan.mall.module.distri.enums.PtSettlemntStatusEnum;
import cn.newfeifan.mall.module.distri.enums.WithdrawalEnum;
import cn.newfeifan.mall.module.distri.enums.WithdrawalResultEnum;
import cn.newfeifan.mall.module.distri.service.applicationforwithdrawal.ApplicationForWithdrawalService;
import cn.newfeifan.mall.module.distri.service.integral.IntegralService;
import cn.newfeifan.mall.module.distri.service.ptdailywithdrawal.PtDailyWithdrawalService;
import cn.newfeifan.mall.module.distri.service.ptprofitlog.PtProfitLogService;
import cn.newfeifan.mall.module.member.service.user.MemberUserService;
import cn.newfeifan.mall.module.system.api.sms.SmsCodeApi;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import cn.newfeifan.mall.module.distri.controller.admin.applicationforwithdrawalchannel.vo.*;
import cn.newfeifan.mall.module.distri.dal.dataobject.applicationforwithdrawalchannel.ApplicationForWithdrawalChannelDO;
import cn.newfeifan.mall.framework.common.pojo.PageResult;
import cn.newfeifan.mall.framework.common.util.object.BeanUtils;

import cn.newfeifan.mall.module.distri.dal.mysql.applicationforwithdrawalchannel.ApplicationForWithdrawalChannelMapper;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.newfeifan.mall.framework.common.util.servlet.ServletUtils.getClientIP;
import static cn.newfeifan.mall.module.distri.constant.DistriConstants.MILLION;
import static cn.newfeifan.mall.module.distri.enums.CaclEnum.WITHDRAWAL_ERROR;
import static cn.newfeifan.mall.module.distri.enums.ErrorCodeConstants.*;

/**
 * 提现渠道记录 Service 实现类
 *
 * @author 非繁人
 */
@Service
@Validated
public class ApplicationForWithdrawalChannelServiceImpl implements ApplicationForWithdrawalChannelService {

    @Resource
    private ApplicationForWithdrawalChannelMapper applicationForWithdrawalChannelMapper;

    @Resource
    private ApplicationForWithdrawalService withdrawalService;

    @Resource
    private PtDailyWithdrawalService ptDailyWithdrawalService;

    @Resource
    private IntegralService integralService;

    @Resource
    private PtProfitLogService ptProfitLogService;

    @Resource
    private SmsCodeApi smsCodeApi;

    @Resource
    private MemberUserService memberUserService;

    @Override
    public Long createApplicationForWithdrawalChannel(ApplicationForWithdrawalChannelSaveReqVO createReqVO) {
        // 插入
        ApplicationForWithdrawalChannelDO applicationForWithdrawalChannel = BeanUtils.toBean(createReqVO, ApplicationForWithdrawalChannelDO.class);
        applicationForWithdrawalChannelMapper.insert(applicationForWithdrawalChannel);
        // 返回
        return applicationForWithdrawalChannel.getId();
    }

    @Override
    public void updateApplicationForWithdrawalChannel(ApplicationForWithdrawalChannelSaveReqVO updateReqVO) {
        // 校验存在
        validateApplicationForWithdrawalChannelExists(updateReqVO.getId());
        // 更新
        ApplicationForWithdrawalChannelDO updateObj = BeanUtils.toBean(updateReqVO, ApplicationForWithdrawalChannelDO.class);
        applicationForWithdrawalChannelMapper.updateById(updateObj);
    }

    @Override
    public void deleteApplicationForWithdrawalChannel(Long id) {
        // 校验存在
        validateApplicationForWithdrawalChannelExists(id);
        // 删除
        applicationForWithdrawalChannelMapper.deleteById(id);
    }

    private void validateApplicationForWithdrawalChannelExists(Long id) {
        if (applicationForWithdrawalChannelMapper.selectById(id) == null) {
            throw exception(APPLICATION_FOR_WITHDRAWAL_CHANNEL_NOT_EXISTS);
        }
    }

    @Override
    public ApplicationForWithdrawalChannelDO getApplicationForWithdrawalChannel(Long id) {
        return applicationForWithdrawalChannelMapper.selectById(id);
    }

    @Override
    public PageResult<ApplicationForWithdrawalChannelDO> getApplicationForWithdrawalChannelPage(ApplicationForWithdrawalChannelPageReqVO pageReqVO) {
        return applicationForWithdrawalChannelMapper.selectPage(pageReqVO);
    }

    @Override
    public void updateApplicationForWithdrawalChannel(Long id) {
        ApplicationForWithdrawalChannelDO channel = applicationForWithdrawalChannelMapper.selectById(id);

        channel.setExcelStatus(true);

        applicationForWithdrawalChannelMapper.updateById(channel);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ApplicationForWithdrawalChannelImportExcelVO> importExcel(List<ApplicationForWithdrawalChannelImportExcelVO> list, Long id) {
        // 格式化时间
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        // 用来记录错误的记录
        List<ApplicationForWithdrawalChannelImportExcelVO> errorList = new ArrayList<>();

        List<ApplicationForWithdrawalDO> withdrawalList = withdrawalService.selectListByChannelId(id);

        // 异常判断
        if (withdrawalList.isEmpty()) {
            ErrorCode ERROR = new ErrorCode(1_002_030_034, "选中行的记录为空！");
            throw exception(ERROR);
        }
        if (list.isEmpty()) {
            ErrorCode ERROR = new ErrorCode(1_002_030_035, "上传的Excel文件中没有数据！");
            throw exception(ERROR);
        }
        if (list.get(0).getMoney() == null || list.get(0).getAccountName() == null || list.get(0).getAccountNumber() == null) {
            ErrorCode ERROR = new ErrorCode(1_002_030_036, "Excel文件中的信息内容不正确！");
            throw exception(ERROR);
        }

        ApplicationForWithdrawalChannelDO applicationForWithdrawalChannelDO = applicationForWithdrawalChannelMapper.selectById(id);
        PtDailyWithdrawalDO ptDailyWithdrawal = ptDailyWithdrawalService.getPtDailyWithdrawal(applicationForWithdrawalChannelDO.getPtDailyWithdrawalId());

        for (ApplicationForWithdrawalChannelImportExcelVO importVO : list) {

            String withdrawalTime = importVO.getPostscript().substring(importVO.getPostscript().indexOf("提现日期: ") + "提现日期: ".length()).trim();
            LocalDateTime withdrawalDateTime = LocalDateTime.parse(withdrawalTime, formatter);

            if (ptDailyWithdrawal.getStartTime().isAfter(withdrawalDateTime) || ptDailyWithdrawal.getEndTime().isBefore(withdrawalDateTime)) {
                ErrorCode ERROR = new ErrorCode(1_002_030_036, "Excel文件中的日期与选择行的日期不匹配！");
                throw exception(ERROR);
            }

            Double money = Double.parseDouble(importVO.getMoney());

            for (ApplicationForWithdrawalDO withdrawalDO : withdrawalList) {
//                withdrawalDO.setAmount(withdrawalDO.getAmount() / DistriConstants.ONE_HUNDRED);
                Double amount = Double.parseDouble(String.valueOf((withdrawalDO.getAmount() / DistriConstants.ONE_HUNDRED)));

                // 当前提提现记录的金额和账号与Excel中的金额和账号一致时
                if (money.equals(amount) &&
                        withdrawalDO.getWithdrawalAccount().equals(importVO.getAccountNumber()) &&
                        withdrawalTime.equals(formatter.format(withdrawalDO.getCreateTime()))
                ) {

                    if (importVO.getPayResult().contains(WithdrawalResultEnum.SUCCESS.getResult()) || importVO.getPayResult().contains("成功")) {
                        withdrawalDO.setStatus(WithdrawalEnum.WITHDRAWAL_SUCCESS.getStatus());
                    } else {
                        withdrawalDO.setStatus(WithdrawalEnum.WITHDRAWAL_FAIL.getStatus());
                        // 记录提现失败的记录
                        errorList.add(importVO);

//                        // 退回用户提现积分数量
//                        IntegralDO integralDO = integralService.selectByUser(withdrawalDO.getUserId());
//                        Long integral = money.longValue() * MILLION;
//
//                        integralDO.setCurrentQuota(integralDO.getCurrentQuota() + integral);
//                        integralService.updateIntegral(BeanUtils.toBean(integralDO, IntegralSaveReqVO.class));
//
//                        // 添加用户积分变动Log
//                        PtProfitLogSaveReqVO ptProfitLogSaveReqVO = PtProfitLogSaveReqVO.builder()
//                                .amount(integral)
//                                .afterAmount(integralDO.getCurrentQuota())
//                                .profitStatus(WITHDRAWAL_ERROR.getType())
//                                .userId(withdrawalDO.getUserId())
//                                .generateUserId(integralDO.getUserId())
//                                .build();
//                        ptProfitLogService.createPtProfitLog(ptProfitLogSaveReqVO);
//
//                        MemberUserDO user = memberUserService.getUser(withdrawalDO.getUserId());
//                        // 发送短信通知用户提现失败
//                        SmsCodeSendReqDTO smsCodeSendReqDTO = SmsCodeSendReqDTO.builder()
//                                .mobile(user.getMobile())
//                                .scene(SmsSceneEnum.MEMBER_WITHDRAWAL_ERROR.getScene())
//                                .createIp(getClientIP())
//                                .sendTime(withdrawalDO.getCreateTime())
//                                .build();
//                        smsCodeApi.sendSmsCode(smsCodeSendReqDTO);
                    }

                    withdrawalService.updateApplicationForWithdrawal(BeanUtils.toBean(withdrawalDO, ApplicationForWithdrawalSaveReqVO.class));
                }
            }
        }

        // 根据导入的记录判断提现结果
        if (errorList.isEmpty()) {
            applicationForWithdrawalChannelDO.setStatus(PtSettlemntStatusEnum.SETTLEMENT.getStatus());
        } else if (errorList.size() < withdrawalList.size()) {
            applicationForWithdrawalChannelDO.setStatus(PtSettlemntStatusEnum.SETTLEMENT_ERROR.getStatus());
        } else if (errorList.size() == withdrawalList.size()) {
            applicationForWithdrawalChannelDO.setStatus(PtSettlemntStatusEnum.SETTLEMENT_SUCCESS.getStatus());
        }

        // 更新状态
        applicationForWithdrawalChannelMapper.updateById(applicationForWithdrawalChannelDO);

        Long allCount = applicationForWithdrawalChannelMapper.selectCount(ApplicationForWithdrawalChannelDO::getPtDailyWithdrawalId, applicationForWithdrawalChannelDO.getPtDailyWithdrawalId());
        Long liteSuccessCount = applicationForWithdrawalChannelMapper.selectCount(PtSettlemntStatusEnum.SETTLEMENT_ERROR.getStatus(), applicationForWithdrawalChannelDO.getPtDailyWithdrawalId());
        Long successCount = applicationForWithdrawalChannelMapper.selectCount(PtSettlemntStatusEnum.SETTLEMENT.getStatus(), applicationForWithdrawalChannelDO.getPtDailyWithdrawalId());

        // 更新一级记录的提现状态
        if (allCount.equals(successCount)) {
            ptDailyWithdrawal.setStatus(PtSettlemntStatusEnum.SETTLEMENT.getStatus());
        } else if (liteSuccessCount > 0) {
            ptDailyWithdrawal.setStatus(PtSettlemntStatusEnum.SETTLEMENT_ERROR.getStatus());
        } else {
            ptDailyWithdrawal.setStatus(PtSettlemntStatusEnum.SETTLEMENT_SUCCESS.getStatus());
        }

        // 更新状态
        ptDailyWithdrawalService.updatePtDailyWithdrawal(BeanUtils.toBean(ptDailyWithdrawal, PtDailyWithdrawalSaveReqVO.class));

        return errorList;

    }

}