package com.yifu.cloud.plus.v1.yifu.salary.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TSettleDomainListVo;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TSettleDomainSelectVo;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.DateUtil;
import com.yifu.cloud.plus.v1.yifu.common.core.util.ExcelUtil;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.ArchivesDaprUtil;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.SocialDaprUtils;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.UpmsDaprUtils;
import com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils;
import com.yifu.cloud.plus.v1.yifu.salary.entity.THaveSalaryNosocial;
import com.yifu.cloud.plus.v1.yifu.salary.mapper.THaveSalaryNosocialMapper;
import com.yifu.cloud.plus.v1.yifu.salary.service.THaveSalaryNosocialService;
import com.yifu.cloud.plus.v1.yifu.salary.service.TSalaryAccountService;
import com.yifu.cloud.plus.v1.yifu.salary.vo.HaveSalaryNoSocialVo;
import com.yifu.cloud.plus.v1.yifu.salary.vo.THaveSalaryNoSocialExportVo;
import com.yifu.cloud.plus.v1.yifu.salary.vo.THaveSalaryNosocialSearchVo;
import com.yifu.cloud.plus.v1.yifu.social.entity.TPaymentInfo;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 有资没有社保(首页提醒定时任务）
 *
 * @author wangan
 * @date 2019-11-26 09:34:58
 */
@AllArgsConstructor
@Service("tHaveSalaryNosocialService")
public class THaveSalaryNosocialServiceImpl extends ServiceImpl<THaveSalaryNosocialMapper, THaveSalaryNosocial> implements THaveSalaryNosocialService {

	private final TSalaryAccountService salaryAccountService;

	@Autowired
	private final SocialDaprUtils socialDaprUtils;

	@Autowired
	private final ArchivesDaprUtil archivesDaprUtil;

	@Autowired
	private final UpmsDaprUtils upmsDaprUtils;
    /**
     * 有资没有社保(首页提醒定时任务）简单分页查询
     *
     * @param tHaveSalaryNosocial 有资没有社保(首页提醒定时任务）
     * @return
     */
    @Override
    public IPage<THaveSalaryNosocial> getTHaveSalaryNosocialPage(Page<THaveSalaryNosocial> page, THaveSalaryNosocial tHaveSalaryNosocial) {
        // TODO 数据权限待处理
		return baseMapper.getTHaveSalaryNosocialPage(page, tHaveSalaryNosocial, null);

    }


    /**
     * 有资没有社保(首页提醒定时任务）简单分页查询
     *
     * @param tHaveSalaryNosocial 有资没有社保(首页提醒定时任务）
     * @return
     */
    @Override
    public IPage<THaveSalaryNosocial> getTHaveSalaryNosocialHandelPage(Page<THaveSalaryNosocial> page, THaveSalaryNosocial tHaveSalaryNosocial) {
        return baseMapper.getTHaveSalaryNosocialHandelPage(page, tHaveSalaryNosocial);
    }

    /**
     * @Author fxj
     * @Description 每月生成有工资没有社保(首页提醒定时任务 ）
	 *有工资无社保提醒 （ 和档案属性在职状态和员工类型无关 ） ：
	 *1.执行时间 ： 每月1号上午六点 salaryTask createHaveSalaryNoSocial
	 *2.判断逻辑 ： 先删除上月 （ 发送EKP时间对应的月份 ） 提醒数据 ， 然后查找连续三个月 （ 不包含当月 ） 有发薪记录 - （ 薪资单状态发送成功 ） ， 但是对应三个月均无社保缴费记录 （ 无个人社保数据 ） 并生成
	 *3.数据消失逻辑 ： 当月不消失 ； 次月定时任务执行的时候删除 ， 重新计算生成
	 *4.反馈 ： 只能反馈创建人为自己的数据
	 *5.导出 ： 可选择 / 按查询条件 / 全量导出 ， 导出字段为列表字段
     * @Date 18:30 2022/8/16
     * @Param
     * @return
	 *  * 1.拉取所有上月社保记录
	 *  * 2.拉取所有上月工资记录
	 *  * 3.查询数据
	 *  * 4.生成记录
    **/
    @Override
    public void generate(String salaryMonth) {
        //重新跑上月数据
        this.remove(Wrappers.<THaveSalaryNosocial>query().lambda().eq(THaveSalaryNosocial::getCreateMonth,salaryMonth));
        List<THaveSalaryNosocial> haveSalaryNosocialList = salaryAccountService.getLastMonthTHaveSalaryNosocial(salaryMonth);
        if(!Common.isNotEmpty(haveSalaryNosocialList)){
            log.error("获取有社保无工资数据为空");
            return;
        }
        //去缴费库查询查询这些人社保是否存在
        Map<String, TPaymentInfo> empPaymentInfoMap=Maps.newHashMap();
        R<HaveSalaryNoSocialVo> noSocialVoR = socialDaprUtils.getPaymentinfoListByEmpdIdCard(Common.listObjectToStrList(haveSalaryNosocialList, "employeeIdCard"), salaryMonth);
        if (Common.isEmpty(noSocialVoR) || noSocialVoR.getCode() == CommonConstants.FAIL){
			log.error("获取社保公积金信息失败");
			return;
		}
		if (Common.isNotNull(noSocialVoR)
				&& Common.isNotNull(noSocialVoR.getData())
				&& Common.isNotNull(noSocialVoR.getData().getPaymentInfos())) {
            for (TPaymentInfo paymentInfo : noSocialVoR.getData().getPaymentInfos()) {
                empPaymentInfoMap.put(paymentInfo.getEmpIdcard(),paymentInfo);
            }
        }
        //结算主体
		R<TSettleDomainListVo> domainListVoR = archivesDaprUtil.selectAllSettleDomainSelectVos();
        HashMap<String, TSettleDomainSelectVo> settleDomainSelectVoMap = Maps.newHashMap();
		if (Common.isEmpty(domainListVoR) || domainListVoR.getCode() == CommonConstants.FAIL){
			log.error("获取项目信息失败");
			return;
		}
		if (Common.isNotNull(domainListVoR)
				&& Common.isNotNull(domainListVoR.getData())
				&& Common.isNotNull(domainListVoR.getData().getListSelectVO()))
        for (TSettleDomainSelectVo selectVo : domainListVoR.getData().getListSelectVO()) {
            settleDomainSelectVoMap.put(selectVo.getId(),selectVo);
        }
        for (THaveSalaryNosocial haveSalaryNosocial : haveSalaryNosocialList) {
            // 有工资无社保    薪酬人员查询 表单类型为薪资的  连续3个月有发薪记录  但是这三个月都没有社保缴费记录
            if (empPaymentInfoMap.get(haveSalaryNosocial.getEmployeeIdCard()) != null) {
                //如果缴费库中有此人身份证号码数据,那他算有社保
                continue;
            }
            //塞客户数据
            TSettleDomainSelectVo selectVo = settleDomainSelectVoMap.get(haveSalaryNosocial.getSettleDomainId());
            haveSalaryNosocial.setCustomerId(selectVo!=null?selectVo.getCustomerId():null);
            haveSalaryNosocial.setCustomerName(selectVo!=null?selectVo.getCustomerName():null);
            haveSalaryNosocial.setCreateTime(LocalDateTime.now());
			haveSalaryNosocial.setCreateMonth(salaryMonth);
            this.save(haveSalaryNosocial);
        }

    }

	public List<THaveSalaryNoSocialExportVo> noPageDiy(THaveSalaryNosocialSearchVo searchVo,
													   List<String> settleDomainIds,
													   List<String> ids,
													   String sql) {
		return baseMapper.noPageDiy(searchVo,settleDomainIds,ids,sql);
	}

	private  int noPageCountDiy(THaveSalaryNosocialSearchVo searchVo,
								 List<String> settleDomainIds,
								 List<String> ids,
								 String sql) {
		return baseMapper.noPageCountDiy(searchVo,settleDomainIds,ids,sql);
	}

	/**
	 * @Author fxj
	 * @Description 消息提醒导出
	 * @Date 15:37 2022/8/17
	 * @Param
	 * @return
	**/
	@Override
	public void listExport(HttpServletResponse response, THaveSalaryNosocialSearchVo searchVo) {
		String fileName = "有工资无社保批量导出" + DateUtil.getThisTime() + CommonConstants.XLSX;
		//获取要导出的列表
		List<THaveSalaryNoSocialExportVo> list = new ArrayList<>();
		// TODO
		List<String> settleDomainIds =null;
		List<String> ids = Common.getList(searchVo.getIds());
		String sql = null;
		int count = noPageCountDiy(searchVo,settleDomainIds,ids,sql);
		ServletOutputStream out = null;
		try {
			out = response.getOutputStream();
			response.setContentType(CommonConstants.MULTIPART_FORM_DATA);
			response.setCharacterEncoding("utf-8");
			response.setHeader(CommonConstants.CONTENT_DISPOSITION, CommonConstants.ATTACHMENT_FILENAME + URLEncoder.encode(fileName  , "UTF-8"));
			// 这里 需要指定写用哪个class去写，然后写到第一个sheet，然后文件流会自动关闭
			ExcelWriter excelWriter = EasyExcel.write(out, THaveSalaryNoSocialExportVo.class).build();
			int index = 0;
			if (count >  CommonConstants.ZERO_INT){
				for (int i = 0; i <= count; ) {
					// 获取实际记录
					searchVo.setLimitStart(i);
					searchVo.setLimitEnd(CommonConstants.EXCEL_EXPORT_LIMIT);
					list = noPageDiy(searchVo,settleDomainIds,ids,sql);
					if (Common.isNotNull(list)){
						ExcelUtil<THaveSalaryNoSocialExportVo> util = new ExcelUtil<>(THaveSalaryNoSocialExportVo.class);
						for (THaveSalaryNoSocialExportVo vo:list){
							util.convertEntity(vo,null,null,null);
						}
					}
					if (Common.isNotNull(list)){
						WriteSheet writeSheet = EasyExcel.writerSheet("消息提醒"+index).build();
						excelWriter.write(list,writeSheet);
						index++;
					}
					i = i + CommonConstants.EXCEL_EXPORT_LIMIT;
					if (Common.isNotNull(list)){
						list.clear();
					}
				}
			}else {
				WriteSheet writeSheet = EasyExcel.writerSheet("消息提醒"+index).build();
				excelWriter.write(list,writeSheet);
			}
			if (Common.isNotNull(list)){
				list.clear();
			}
			out.flush();
			excelWriter.finish();
		}catch (Exception e){
			log.error("执行异常" ,e);
		}finally {
			try {
				if (null != out) {
					out.close();
				}
			} catch (IOException e) {
				log.error("执行异常", e);
			}
		}
	}

	/**
	 * @Author fxj
	 * @Description 反馈信息
	 * @Date 17:23 2022/8/17
	 * @Param
	 * @return
	**/
	@Override
	public R<String> feedback(Integer reasonType, String id, String feedBack) {
		YifuUser user = SecurityUtils.getUser();
		if (Common.isEmpty(user)){
			return R.failed(CommonConstants.USER_FAIL);
		}
		THaveSalaryNosocial  entity = baseMapper.selectById(id);
		if (Common.isEmpty(entity)){
			return R.failed(CommonConstants.PARAM_IS_NOT_ERROR);
		}
		if (!user.getId().equals(entity.getCreateBy())){
			return R.failed("允许创建人反馈信息！");
		}
		entity.setReasonType(reasonType);
		entity.setFeedBack(feedBack);
		int res  = baseMapper.updateById(entity);
		if (res == CommonConstants.ONE_INT_NEGATE){
			return R.failed(CommonConstants.SAVE_FAILED);
		}
		return R.ok(null,CommonConstants.SAVE_SUCCESS);
	}
}
