package com.simuwang.manage.service.impl;

import com.simuwang.base.common.enums.DeletionType;
import com.simuwang.base.common.enums.OpenStatusType;
import com.simuwang.base.common.enums.ResultCode;
import com.simuwang.base.common.util.DateUtils;
import com.simuwang.base.common.util.EmailUtil;
import com.simuwang.base.common.util.ExcelUtil;
import com.simuwang.base.common.util.StringUtil;
import com.simuwang.base.mapper.CompanyEmailConfigMapper;
import com.simuwang.base.mapper.CompanyEmailSendHistoryMapper;
import com.simuwang.base.mapper.DeletionInfoMapper;
import com.simuwang.base.mapper.FundInfoMapper;
import com.simuwang.base.pojo.dos.CompanyEmailConfigDO;
import com.simuwang.base.pojo.dos.CompanyEmailSendHistoryDO;
import com.simuwang.base.pojo.dos.EmailDeletionInfoDO;
import com.simuwang.base.pojo.dto.ExcelDeletionInfoDTO;
import com.simuwang.base.pojo.dto.MailboxInfoDTO;
import com.simuwang.base.pojo.vo.CompanyEmailConfigVO;
import com.simuwang.manage.service.CompanyEmailConfigService;
import com.smppw.common.pojo.ResultVo;
import jakarta.annotation.Resource;
import jakarta.mail.Message;
import jakarta.mail.Store;
import jakarta.mail.internet.MimeMessage;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * FileName: CompanyEmailConfigServiceImpl
 * Author:   chenjianhua
 * Date:     2024/9/7 12:55
 * Description: ${DESCRIPTION}
 */
@Service
public class CompanyEmailConfigServiceImpl implements CompanyEmailConfigService {
    @Autowired
    private CompanyEmailConfigMapper companyEmailConfigMapper;

    @Autowired
    private CompanyEmailSendHistoryMapper companyEmailSendHistoryMapper;
    @Autowired
    private FundInfoMapper fundInfoMapper;
    @Autowired
    private DeletionInfoMapper deletionInfoMapper;
    @Resource
    private JavaMailSender javaMailSender;

    @Value("${email.file.path}")
    private String path;
    @Value("${spring.mail.username}")
    private String account;
    @Value("${spring.mail.password}")
    private String password;
    @Value("${spring.mail.host}")
    private String host;
    @Value("${spring.mail.port}")
    private String port;
    @Value("${spring.mail.protocol}")
    private String protocol;
    @Override
    public ResultVo saveCompanyEmailConfig(List<CompanyEmailConfigVO> companyEmailConfigVOS) {
        ResultVo vo = new ResultVo(com.smppw.common.pojo.enums.status.ResultCode.SAVE_SUCCESS);
        vo.setData(true);
        StringBuffer msg = new StringBuffer();
        try{
            for(CompanyEmailConfigVO emailConfigVO : companyEmailConfigVOS){
                CompanyEmailConfigDO oldEmailConfigDO = companyEmailConfigMapper.selectEmailConfig(emailConfigVO.getCompanyId(),emailConfigVO.getEmail());
                if(!StringUtil.isNull(oldEmailConfigDO) && emailConfigVO.getId() == null){
                    msg.append(emailConfigVO.getCompanyName()+"已存在邮箱"+emailConfigVO.getEmail()).append(",");
                }
                if(!StringUtil.isNull(oldEmailConfigDO) && emailConfigVO.getId() != null){
                    if(!oldEmailConfigDO.getId().equals(emailConfigVO.getId())){
                        msg.append(emailConfigVO.getCompanyName()+"已存在邮箱"+emailConfigVO.getEmail()).append(",");
                    }
                }
            }
            if(StringUtil.isNotEmpty(msg.toString())){
                vo.setMsg(msg.toString().substring(0,msg.length()-1));
                vo.setData(false);
                return vo;
            }
            for(CompanyEmailConfigVO emailConfigVO : companyEmailConfigVOS){
                CompanyEmailConfigDO emailConfigDO = new CompanyEmailConfigDO();
                emailConfigDO.setCompanyId(emailConfigVO.getCompanyId());
                emailConfigDO.setCompanyName(emailConfigVO.getCompanyName());
                emailConfigDO.setEmail(emailConfigVO.getEmail());
                emailConfigDO.setOpenStatus(emailConfigVO.getOpenStatus());
                emailConfigDO.setRemark(emailConfigVO.getSendRemark());
                emailConfigDO.setIsvalid(1);
                emailConfigDO.setUpdateTime(new Date());
                if(emailConfigVO.getId() != null){
                    emailConfigDO.setId(emailConfigVO.getId());
                    companyEmailConfigMapper.updateCompanyEmailConfig(emailConfigDO);
                }else{
                    emailConfigDO.setCreateTime(new Date());
                    companyEmailConfigMapper.saveCompanyEmailConfig(emailConfigDO);
                }
            }

        }catch (Exception e){

        }
        return vo;
    }

    @Override
    public void deleteCompanyEmailConfig(Integer id) {
        CompanyEmailConfigDO configDO = companyEmailConfigMapper.selectById(id);
        if (configDO != null) {
            configDO.setIsvalid(0);
            configDO.setUpdateTime(new Date());
            companyEmailConfigMapper.updateById(configDO);
        }
    }

    @Override
    public void updateCompanyEmailConfig(CompanyEmailConfigVO companyEmailConfigVO) {
        CompanyEmailConfigDO configDO = companyEmailConfigMapper.selectCompanyEmailConfigById(companyEmailConfigVO.getId());
        if(configDO != null){
            configDO.setEmail(companyEmailConfigVO.getEmail());
            configDO.setCompanyId(companyEmailConfigVO.getCompanyId());
            configDO.setCompanyName(companyEmailConfigVO.getCompanyName());
            configDO.setUpdateTime(new Date());
            companyEmailConfigMapper.updateCompanyEmailConfig(configDO);
        }
    }

    @Override
    public void sendCompanyEmail(List<Integer> idList) {
        List<CompanyEmailConfigDO> configDOList = companyEmailConfigMapper.selectCompanyEmailConfigByIdList(idList);
        Map<String,List<CompanyEmailConfigDO>> companyListMap = configDOList.stream().collect(Collectors.groupingBy(e -> e.getCompanyId()));
        for(String companyId : companyListMap.keySet()){
            StringBuffer emails = new StringBuffer();
            List<CompanyEmailConfigDO> configDOS = companyListMap.get(companyId);
            for(CompanyEmailConfigDO configDO: configDOS){
                emails.append(configDO.getEmail()).append(";");
            }
            //把缺失数据的邮件发送到该公司名下的邮箱地址
            sendEmail(companyId,emails.toString());
        }
    }
    @Override
    //邮件校验处理
    public void sendEmail(String companyId, String emails) {
        List<String> fundIdList = fundInfoMapper.getFundIdByCompanyId(companyId);
        if(fundIdList.size() < 1){
            return;
        }
        List<EmailDeletionInfoDO> emailDeletionInfoDOS = deletionInfoMapper.getDeletionInfoByFundId(fundIdList);
        for(EmailDeletionInfoDO infoDO : emailDeletionInfoDOS){
            infoDO.setDeletionType(DeletionType.getDeletionTypeByCode(Integer.valueOf(infoDO.getDeletionType())).getInfo());
        }
        if(emailDeletionInfoDOS.size() > 0){
            //将数据写入excel文件
            File file = writeExcelFile(emailDeletionInfoDOS);
            file.setWritable(true);
            file.setReadable(true);
            file.setExecutable(true);
            try {
                MailboxInfoDTO dto = getFromEmailInfo();
                EmailUtil.senEmail(dto,emails,file,javaMailSender);
                //发送成功之后修改数据为已发送
                deletionInfoMapper.updateSendStatusByFundId(fundIdList);
                //写入发送历史
                String[] emailList = emails.split(";");
                for(String email : emailList){
                    saveCompanyEmailSendHistory(companyId,email,1,ResultCode.SEND_SUCCESS.getMsg());
                }
            } catch (Exception e) {
                String[] emailList = emails.split(";");
                for(String email : emailList){
                    saveCompanyEmailSendHistory(companyId,email,0,e.getMessage());
                }
                throw new RuntimeException(e);
            }
        }
    }

    private void saveCompanyEmailSendHistory(String companyId, String email,Integer sendStatus,String msg) {
        CompanyEmailSendHistoryDO historyDO = new CompanyEmailSendHistoryDO();
        historyDO.setCompanyId(companyId);
        historyDO.setEmail(email);
        historyDO.setSendStatus(sendStatus);
        historyDO.setSendRemark(msg);
        historyDO.setIsvalid(1);
        historyDO.setSendTime(DateUtils.getNowDate());
        historyDO.setCreateTime(DateUtils.getNowDate());
        historyDO.setCreateTime(DateUtils.getNowDate());
        companyEmailSendHistoryMapper.saveCompanyEmailSendHistory(historyDO);
    }


    private MailboxInfoDTO getFromEmailInfo(){
        MailboxInfoDTO dto = new MailboxInfoDTO();
        dto.setAccount(account);
        dto.setProtocol(protocol);
        dto.setPassword(password);
        dto.setPort(port);
        dto.setHost(host);
        return dto;
    }

    private File writeExcelFile(List<EmailDeletionInfoDO> emailDeletionInfoDOS) {
        Map<String,List<List<String>>> values = new HashMap<>();
        List<String> head = new ArrayList<>();
        head.add("基金全称");
        head.add("管理人");
        head.add("缺失类型");
        head.add("缺失日期");
        String sheetName = "基金缺失明细";
        List<List<String>> dataList = new ArrayList<>();
        for(EmailDeletionInfoDO dto : emailDeletionInfoDOS){
            List<String> data = new ArrayList<>();
            data.add(dto.getFundName());
            data.add(dto.getCompanyName());
            data.add(dto.getDeletionType());
            data.add(dto.getDeletionDate());
            dataList.add(data);
        }
        values.put(sheetName,dataList);
        HSSFWorkbook wb = ExcelUtil.getHSSFWorkbook(sheetName,head,values,null);
        File file = new File(path+"/"+DateUtils.format(new Date(),DateUtils.YYYYMMDDHHMMSS)+"基金缺失明细.xls");
        if(!file.exists()){
            try {
                file.createNewFile();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        try {
            wb.write(file);
            wb.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return file;
    }
}
