package com.crm.pay.service.impl;

import com.alibaba.fastjson.JSON;
import com.crm.pay.dao.mapper.FinanceTrainMapper;
import com.crm.pay.dao.repository.FinanceTrainRepository;
import com.crm.pay.service.CustomInfoService;
import com.crm.pay.service.FinanceTrainService;
import com.crm.pay.service.SysConfigService;
import com.crm.pay.service.UserInfoService;
import com.crm.rely.backend.core.constant.Constants;
import com.crm.rely.backend.core.constant.MapConstants;
import com.crm.rely.backend.core.constant.StatusConstants;
import com.crm.rely.backend.core.dto.base.BaseReportResultDto;
import com.crm.rely.backend.core.dto.base.BaseResultDto;
import com.crm.rely.backend.core.dto.base.PageDto;
import com.crm.rely.backend.core.dto.base.ResultWithPagerDto;
import com.crm.rely.backend.core.entity.system.email.SysEmailSendEntity;
import com.crm.rely.backend.core.entity.web.notice.record.WebNoticeRecordAndEmailMqEntity;
import com.crm.rely.backend.core.pojo.table.SysConfigTable;
import com.crm.rely.backend.core.exception.ServiceException;
import com.crm.rely.backend.model.constant.ConfigConstants;
import com.crm.rely.backend.model.constant.EmailTemplateConstants;
import com.crm.rely.backend.model.constant.PayConstants;
import com.crm.rely.backend.model.dto.finance.train.FinanceTrainDto;
import com.crm.rely.backend.model.dto.report.FinanceTrainReportListDto;
import com.crm.rely.backend.model.dto.report.FinanceTrainReportSumDto;
import com.crm.rely.backend.model.dto.report.FinanceTrainSalesReportListDto;
import com.crm.rely.backend.model.entity.custom.login.CustomLoginCheckByLoginEntity;
import com.crm.rely.backend.model.entity.finance.train.FinanceTrainAddEntity;
import com.crm.rely.backend.model.entity.finance.train.FinanceTrainApproveEntity;
import com.crm.rely.backend.model.entity.finance.train.FinanceTrainSearchListEntity;
import com.crm.rely.backend.model.pojo.table.CustomInfoTable;
import com.crm.rely.backend.model.pojo.table.FinanceTrainTable;
import com.crm.rely.backend.model.pojo.table.UserInfoTable;
import com.crm.rely.backend.model.pojo.view.FinanceTrainView;
import com.crm.rely.backend.model.util.CustomInfoUtil;
import com.crm.rely.backend.service.EmailService;
import com.crm.rely.backend.service.MqSendService;
import com.crm.rely.backend.util.DateUtil;
import com.crm.rely.backend.util.FormatPage;
import com.crm.rely.backend.util.GetRandom;
import com.crm.rely.backend.util.NameUtil;
import com.google.common.base.Strings;
import lombok.extern.log4j.Log4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.BeanUtils;
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.*;

/**
 * @Author: houn
 * @Date: 2020/11/23 23:24
 * @Description:
 */
@Log4j
@Service
public class FinanceTrainServiceImpl implements FinanceTrainService {

    @Autowired
    private FinanceTrainRepository repository;

    @Autowired
    private CustomInfoService customInfoService;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private FinanceTrainMapper mapper;

    @Autowired
    private SysConfigService sysConfigService;

    @Autowired
    private EmailService emailService;

    @Autowired
    private MqSendService mqSendService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(FinanceTrainAddEntity entity) throws ServiceException {

        List<Integer> st = new ArrayList<>(2);
        st.add(StatusConstants.APPLY_STATUS);
        st.add(StatusConstants.PASSED_STATUS);
        if (repository.existsByCustomIdAndLoginAndStatusIn(entity.getCustomId(), entity.getLogin(), st)) {
            throw ServiceException.exception(Constants.APPLY_EXISTS);
        }
        //获取交易账户
        CustomInfoTable customInfoTable = getCustom(entity);
        entity.setCustomId(customInfoTable.getId());
        String name = entity.getName();
        if (Strings.isNullOrEmpty(name)) {

            //获取客户名称
            name = CustomInfoUtil.getName(customInfoTable);
        }

        //生成流水号
        String serial = getOrderNo();

        //构建添加实体
        FinanceTrainTable table = new FinanceTrainTable();

        BeanUtils.copyProperties(entity, table);
        table.setName(name);
        table.setAgentId(customInfoTable.getAgentId());
        table.setCId(customInfoTable.getCId());

        table.setStatus(StatusConstants.APPLY_STATUS);
        table.setSerial(serial);

        repository.save(table);
        sendTrainEmail(table);
    }

    @Override
    public ResultWithPagerDto<FinanceTrainDto> searchPageList(FinanceTrainSearchListEntity entity) throws ServiceException {
        Integer count = mapper.countList(entity);
        PageDto pageDto = PageDto.format(entity, count);
        if (count == null || count <= 0) {
            return ResultWithPagerDto.success(pageDto);
        }

        BaseResultDto<List<FinanceTrainDto>> listBaseResultDto = searchList(entity);

        return ResultWithPagerDto.success(pageDto, listBaseResultDto.getData());
    }

    @Override
    public BaseResultDto<List<FinanceTrainDto>> searchList(FinanceTrainSearchListEntity entity) throws ServiceException {

        List<FinanceTrainView> views = mapper.searchList(entity);

        if (views == null || views.size() <= 0) {

            throw new ServiceException(Constants.SYSTEM_ERROR);
        }
        List<FinanceTrainDto> dtos = new ArrayList<>(views.size());

        for (FinanceTrainView view : views) {
            FinanceTrainDto transform = transform(view);
            dtos.add(transform);
        }

        return BaseResultDto.success(dtos);
    }

    @Override
    public FinanceTrainDto searchSingle(Long id) throws ServiceException {
        FinanceTrainView view = mapper.getOne(id);
        if (view == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        return transform(view);
    }

    @Override
    public boolean validateLogin(CustomLoginCheckByLoginEntity entity) throws ServiceException {
        return repository.existsByCustomIdAndLoginAndStatus(entity.getCustomId(), entity.getLogin(), StatusConstants.PASSED_STATUS);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approve(FinanceTrainApproveEntity entity) throws ServiceException {
        FinanceTrainTable financeTrainTable = repository.findFirstById(entity.getId());
        if (financeTrainTable == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        if (StatusConstants.PASSED_STATUS.equals(financeTrainTable.getStatus())) {
            throw ServiceException.exception(Constants.NOT_PERMIT);
        }
        BeanUtils.copyProperties(entity, financeTrainTable);
        repository.save(financeTrainTable);

        //如果同意 则添加培训费佣金
        if (StatusConstants.PASSED_STATUS.equals(entity.getStatus())) {
            //获取账户的代理
            UserInfoTable userInfoTable = userInfoService.getByAgentId(financeTrainTable.getAgentId());

            //判断代理id存在且代理存在 代理id对应的是客户 则给对应客户添加佣金
            /*if (userInfoTable != null && userInfoTable.getCId() != null) {
                customInfoService.updateCnyAmountByCId(userInfoTable.getCId(), new BigDecimal(100), "培训费佣金");
            } else {
                log.info("agent:" + JSON.toJSONString(userInfoTable));
            }*/
        }


        sendCustomEmail(financeTrainTable);
    }

    @Override
    public BaseReportResultDto<List<FinanceTrainReportListDto>, FinanceTrainReportSumDto> report(FinanceTrainSearchListEntity entity) throws Exception {

        Integer count = mapper.countReport(entity);
        if (count == null || count == 0) {
            return new BaseReportResultDto<>(Constants.SUCCESS_CODE, "");
        }
        PageDto pageDto = FormatPage.format(entity.getPage(), count);

        List<FinanceTrainReportListDto> dtos = getReportList(entity);

        FinanceTrainView sumView = mapper.sumReport(entity);
        FinanceTrainReportSumDto sumDto = new FinanceTrainReportSumDto();
        sumDto.setAmount(sumView.getAmount().setScale(2, BigDecimal.ROUND_HALF_UP));

        return new BaseReportResultDto<>(dtos, sumDto, pageDto);
    }

    @Override
    public BaseResultDto<List<FinanceTrainReportListDto>> reportExport(FinanceTrainSearchListEntity entity) throws Exception {

        return BaseResultDto.success(getReportList(entity));
    }

    @Override
    public BaseReportResultDto<List<FinanceTrainSalesReportListDto>, FinanceTrainReportSumDto> salesReport(FinanceTrainSearchListEntity entity) throws Exception {

        Integer count = mapper.countReport(entity);
        if (count == null || count == 0) {
            return new BaseReportResultDto<>(Constants.SUCCESS_CODE, "");
        }
        PageDto pageDto = FormatPage.format(entity.getPage(), count);

        List<FinanceTrainSalesReportListDto> dtos = getSalesReportList(entity);

        FinanceTrainView sumView = mapper.sumReport(entity);
        FinanceTrainReportSumDto sumDto = new FinanceTrainReportSumDto();
        sumDto.setAmount(new BigDecimal(sumView.getAmount().floatValue() * 0.2).setScale(2, BigDecimal.ROUND_HALF_UP));

        return new BaseReportResultDto<>(dtos, sumDto, pageDto);
    }

    @Override
    public BaseResultDto<List<FinanceTrainSalesReportListDto>> salesReportExport(FinanceTrainSearchListEntity entity) throws Exception {
        return BaseResultDto.success(getSalesReportList(entity));
    }


    private List<FinanceTrainReportListDto> getReportList(FinanceTrainSearchListEntity entity) throws Exception {

        List<FinanceTrainView> views = mapper.listReport(entity);
        List<FinanceTrainReportListDto> dtos = Lists.newArrayList();
        for (FinanceTrainView view : views) {
            FinanceTrainReportListDto dto = new FinanceTrainReportListDto();
            BeanUtils.copyProperties(view, dto);
            dtos.add(dto);
            dto.setAmount(dto.getAmount().setScale(2, BigDecimal.ROUND_HALF_UP));
            dto.setCustomName(NameUtil.getName(view.getCountry(), view.getFirstName(), view.getMiddle(), view.getLastName()));
            dto.setIbNo(view.getAgentIbNo());
            dto.setSalesNo(view.getSalesIbNo());
            dto.setCustomId(view.getCId());
        }
        return dtos;
    }

    private List<FinanceTrainSalesReportListDto> getSalesReportList(FinanceTrainSearchListEntity entity) throws Exception {

        List<FinanceTrainView> views = mapper.listReport(entity);
        List<FinanceTrainSalesReportListDto> dtos = Lists.newArrayList();
        for (FinanceTrainView view : views) {
            FinanceTrainSalesReportListDto dto = new FinanceTrainSalesReportListDto();
            BeanUtils.copyProperties(view, dto);
            dtos.add(dto);
            dto.setAmount(new BigDecimal(view.getAmount().floatValue() * 0.2).setScale(2, BigDecimal.ROUND_HALF_UP));
            dto.setCustomName(NameUtil.getName(view.getCountry(), view.getFirstName(), view.getMiddle(), view.getLastName()));
            dto.setIbNo(view.getAgentIbNo());
            dto.setSalesNo(view.getSalesIbNo());
            dto.setCustomId(view.getCId());
            dto.setSalesName(view.getSalesName());
        }
        return dtos;
    }

    private void sendTrainEmail(FinanceTrainTable table) throws ServiceException {

        SysConfigTable sysConfigTable = sysConfigService.getByCode(ConfigConstants.FINANCE_TRAIN_MANAGER_EMAIL);
        if (sysConfigTable == null) {
            throw new ServiceException(Constants.SYSTEM_ERROR);
        }
        String users = sysConfigTable.getValue();

        if (users == null) {
            throw new ServiceException(Constants.SYSTEM_ERROR);
        }
        //构建map 用于后面邮件模版替换
        Map<String, String> map = new HashMap<>(10);

        map.put(MapConstants.LOGIN, table.getLogin() + "");

        map.put(MapConstants.NAME, table.getName());

        map.put(MapConstants.AMOUNT, table.getAmount() == null ? "" : String.format("%.2f", table.getAmount().doubleValue()));
        map.put(MapConstants.APPLY_TIME, DateUtil.formatTime(table.getAddTime()));
        map.put(MapConstants.SERIAL, table.getSerial());
        map.put(MapConstants.DATE_TIME, DateUtil.formatTime(new Date()));

        SysEmailSendEntity sysEmailSendEntity = new SysEmailSendEntity();
        sysEmailSendEntity.setSubject("CWG DEPOSIT");
        sysEmailSendEntity.setMap(map);
        sysEmailSendEntity.setTemplateName(EmailTemplateConstants.FINANCE_TRAIN_NOTICE_NAME);
        sysEmailSendEntity.setUsers(users);
        try {
            emailService.sendEmail(sysEmailSendEntity);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void sendCustomEmail(FinanceTrainTable table) throws ServiceException {

        CustomInfoTable customInfoTable = customInfoService.getById(table.getCustomId());
        if (customInfoTable == null) {
            throw new ServiceException(Constants.USER_NOT_EXIST_ERROR);
        }
        //构建map 用于后面邮件模版替换
        Map<String, String> map = new HashMap<>(10);

        map.put(MapConstants.NAME, table.getName());
        map.put(MapConstants.LOGIN, String.valueOf(table.getLogin()));
        map.put(MapConstants.DATE_TIME, DateUtil.formatTime(new Date()));
        map.put(MapConstants.APPROVE_DESC, table.getApproveDesc());
        map.put(MapConstants.APPROVE_STATUS, table.getStatus().equals(2) ? "通过" : "拒绝");

        SysEmailSendEntity sysEmailSendEntity = new SysEmailSendEntity();
        sysEmailSendEntity.setSubject("CWG DEPOSIT");
        sysEmailSendEntity.setMap(map);

        sysEmailSendEntity.setTemplateName(EmailTemplateConstants.FINANCE_TRAIN_APPROVE_NOTICE_RESULT);

        sysEmailSendEntity.setUsers(customInfoTable.getEmail());
        try {
            emailService.sendEmail(sysEmailSendEntity);
            WebNoticeRecordAndEmailMqEntity mqEntity = new WebNoticeRecordAndEmailMqEntity(sysEmailSendEntity,
                    table.getCId(), table.getCustomId());
            mqSendService.send(Constants.WEB_NOTICE_PUT_RECORD, mqEntity);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private FinanceTrainDto transform(FinanceTrainView financeDepositView) {
        FinanceTrainDto dto = new FinanceTrainDto();
        BeanUtils.copyProperties(financeDepositView, dto);
        return dto;
    }


    private CustomInfoTable getCustom(FinanceTrainAddEntity entity) throws ServiceException {
        CustomInfoTable customInfoTable = customInfoService.getById(entity.getCustomId());

        return customInfoTable;
    }

    private String getOrderNo() {
        /**
         * 生成订单号
         */
        String orderNo = GetRandom.getOrderNo(PayConstants.FINANCE_TRAIN);
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return orderNo;
    }
}
