package com.yifu.cloud.plus.v1.yifu.insurances.service.insurance.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
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.yifu.cloud.plus.v1.yifu.archives.vo.EmployeeRegistrationPreVo;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TSettleDomainRegistListVo;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.ClientNameConstants;
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.LocalDateTimeUtils;
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.security.util.SecurityUtils;
import com.yifu.cloud.plus.v1.yifu.insurances.entity.TEmployeeInsurancePre;
import com.yifu.cloud.plus.v1.yifu.insurances.mapper.insurances.TEmployeeInsurancePreMapper;
import com.yifu.cloud.plus.v1.yifu.insurances.service.insurance.ScheduleService;
import com.yifu.cloud.plus.v1.yifu.insurances.service.insurance.TEmployeeInsurancePreService;
import com.yifu.cloud.plus.v1.yifu.insurances.service.insurance.TInsuranceDetailService;
import com.yifu.cloud.plus.v1.yifu.insurances.util.LocalDateUtil;
import com.yifu.cloud.plus.v1.yifu.insurances.vo.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 商险待办任务表
 *
 * @author huych
 * @date 2025-03-31 12:25:13
 */
@Log4j2
@Service
@RequiredArgsConstructor
public class TEmployeeInsurancePreServiceImpl extends ServiceImpl<TEmployeeInsurancePreMapper, TEmployeeInsurancePre> implements TEmployeeInsurancePreService {

	@Autowired
	private ArchivesDaprUtil archivesDaprUtil;

	@Autowired
	@Lazy
	private TInsuranceDetailService detailService;

	@Autowired
	@Lazy
	private ScheduleService scheduleService;

	/**
	 * 商险待办任务表简单分页查询
	 *
	 * @param tEmployeeInsurancePre 商险待办任务表
	 * @return
	 */
	@Override
	public IPage<TEmployeeInsurancePre> getTEmployeeInsurancePrePage(Page<TEmployeeInsurancePre> page, TEmployeeInsurancePreSearchVo tEmployeeInsurancePre) {
		//权限赋值
		initSearchVo(tEmployeeInsurancePre);
		return baseMapper.getTEmployeeInsurancePrePage(page, tEmployeeInsurancePre);
	}

	/**
	 * 商险待办任务表批量导出
	 *
	 * @param searchVo 商险待办任务表
	 * @return
	 */
	@Override
	public void listExport(HttpServletResponse response, TEmployeeInsurancePreSearchVo searchVo) {
		String fileName = "商险待办任务表批量导出" + DateUtil.getThisTime() + ".xlsx";
		//获取要导出的列表
		List<TEmployeeInsurancePreExportVo> list = new ArrayList<>();
		long count = baseMapper.selectExportCount(searchVo);
		try (ServletOutputStream out= response.getOutputStream();){
			response.setContentType(CommonConstants.MULTIPART_FORM_DATA);
			response.setCharacterEncoding("utf-8");
			response.setHeader(CommonConstants.CONTENT_DISPOSITION, CommonConstants.ATTACHMENT_FILENAME + URLEncoder.encode(fileName, CommonConstants.UTF8));
			// 这里 需要指定写用哪个class去写，然后写到第一个sheet，然后文件流会自动关闭
			ExcelWriter excelWriter = EasyExcel.write(out, TEmployeeInsurancePreExportVo.class).build();
			int index = 0;
			if (count > CommonConstants.ZERO_INT) {
				for (int i = 0; i <= count; i += CommonConstants.EXCEL_EXPORT_LIMIT) {
					// 获取实际记录
					searchVo.setLimitStart(i);
					searchVo.setLimitEnd(CommonConstants.EXCEL_EXPORT_LIMIT);
					list = baseMapper.selectExportList(searchVo);
					if (Common.isNotNull(list)) {
						WriteSheet writeSheet = EasyExcel.writerSheet("商险待办任务表" + index).build();
						excelWriter.write(list, writeSheet);
						index++;
					}
					if (Common.isNotNull(list)) {
						list.clear();
					}
				}
			} else {
				WriteSheet writeSheet = EasyExcel.writerSheet("商险待办任务表" + index).build();
				excelWriter.write(list, writeSheet);
			}
			if (Common.isNotNull(list)) {
				list.clear();
			}
			excelWriter.finish();
		} catch (Exception e) {
			log.error("执行异常", e);
		}
	}

	@Override
	public R confirm(List<String> idList) {
		List<TEmployeeInsurancePre> insurancePreList = baseMapper.selectList(Wrappers.<TEmployeeInsurancePre>query()
				.lambda().in(TEmployeeInsurancePre::getId, idList)
				.eq(TEmployeeInsurancePre::getProcessStatus, CommonConstants.ZERO_STRING));
		if (Common.isEmpty(insurancePreList)) {
			return R.failed(CommonConstants.NO_DATA_TO_HANDLE);
		}
		LambdaUpdateWrapper<TEmployeeInsurancePre> updateWrapper = new LambdaUpdateWrapper<>();
		updateWrapper.in(TEmployeeInsurancePre::getId,idList)
				.eq(TEmployeeInsurancePre::getProcessStatus, CommonConstants.ZERO_STRING)
				.set(TEmployeeInsurancePre::getProcessStatus, CommonConstants.ONE_STRING);
		this.update(updateWrapper);
		return R.ok();
	}

	@Override
	public R batchDispatcherInsurance(List<String> idList) {
		List<TEmployeeInsurancePre> insurancePreList = baseMapper.selectList(Wrappers.<TEmployeeInsurancePre>query()
				.lambda().in(TEmployeeInsurancePre::getId, idList)
				.in(TEmployeeInsurancePre::getProcessStatus, CommonConstants.processInsurancesStatus));
		if (Common.isEmpty(insurancePreList)) {
			return R.failed(CommonConstants.NO_DATA_TO_HANDLE);
		}
		List<InsuranceAddParam> addParamList = new ArrayList<>();
		List<InsuranceBatchParam> batchAddParamList = new ArrayList<>();
		List<InsuranceReplaceParam> replaceAddParamList = new ArrayList<>();
		for (TEmployeeInsurancePre insurancePre : insurancePreList) {
			//新增、批增、替换
			if (CommonConstants.ONE_INT == insurancePre.getBuyType()) {
				InsuranceAddParam addParam = new InsuranceAddParam();
				addParam.setEmpName(insurancePre.getEmployeeName());
				addParam.setEmpIdcardNo(insurancePre.getEmpIdcard());
				addParam.setDeptNo(insurancePre.getDeptNo());
				addParam.setInsuranceCompanyName(insurancePre.getInsuranceCompanyName());
				addParam.setInsuranceTypeName(insurancePre.getInsuranceTypeName());
				addParam.setPolicyStart(DateUtil.dateToString(insurancePre.getPolicyStart(),DateUtil.ISO_EXPANDED_DATE_FORMAT));
				addParam.setPolicyEnd(DateUtil.dateToString(insurancePre.getPolicyEnd(),DateUtil.ISO_EXPANDED_DATE_FORMAT));
				addParam.setBuyStandard(insurancePre.getBuyStandard());
				addParam.setInsuranceProvinceName(insurancePre.getFileProvince());
				addParam.setInsuranceCityName(insurancePre.getFileCity());
				addParam.setSettleMonth(CommonConstants.EMPTY_STRING);
				addParam.setPost(insurancePre.getPosition());
				addParam.setRemark(CommonConstants.EMPTY_STRING);
				addParamList.add(addParam);
			}
			if (CommonConstants.TWO_INT == insurancePre.getBuyType()) {
				InsuranceBatchParam addParam = new InsuranceBatchParam();
				addParam.setEmpName(insurancePre.getEmployeeName());
				addParam.setEmpIdcardNo(insurancePre.getEmpIdcard());
				addParam.setDeptNo(insurancePre.getDeptNo());
				addParam.setInsuranceCompanyName(insurancePre.getInsuranceCompanyName());
				addParam.setInsuranceTypeName(insurancePre.getInsuranceTypeName());
				addParam.setPolicyNo(insurancePre.getPolicyNo());
				addParam.setBuyStandard(insurancePre.getBuyStandard());
				addParam.setInsuranceProvinceName(insurancePre.getFileProvince());
				addParam.setInsuranceCityName(insurancePre.getFileCity());
				addParam.setSettleMonth(CommonConstants.EMPTY_STRING);
				addParam.setPost(insurancePre.getPosition());
				addParam.setRemark(CommonConstants.EMPTY_STRING);
				batchAddParamList.add(addParam);
			}
			if (CommonConstants.THREE_INT == insurancePre.getBuyType()) {
				InsuranceReplaceParam addParam = new InsuranceReplaceParam();
				addParam.setEmpName(insurancePre.getEmployeeName());
				addParam.setEmpIdcardNo(insurancePre.getEmpIdcard());
				addParam.setDeptNo(insurancePre.getDeptNo());
				addParam.setInsuranceCompanyName(insurancePre.getInsuranceCompanyName());
				addParam.setInsuranceTypeName(insurancePre.getInsuranceTypeName());
				addParam.setBuyStandard(insurancePre.getBuyStandard());
				addParam.setPolicyStart(DateUtil.dateToString(insurancePre.getPolicyStart(),DateUtil.ISO_EXPANDED_DATE_FORMAT));
				addParam.setPolicyEnd(DateUtil.dateToString(insurancePre.getPolicyEnd(),DateUtil.ISO_EXPANDED_DATE_FORMAT));
				addParam.setPost(insurancePre.getPosition());
				addParam.setReplaceEmpName(insurancePre.getReplaceEmployeeName());
				addParam.setReplaceDeptNo(insurancePre.getReplaceDeptNo());
				addParam.setReplaceEmpIdcardNo(insurancePre.getReplaceEmpIdcard());
				//todo
//			addParam.setRemark(CommonConstants.EMPTY_STRING);
				replaceAddParamList.add(addParam);
			}
		}
		//组装返回给前端
		List<InsuranceAddParam> paramList = new ArrayList<>();
		List<InsuranceBatchParam> batchParamList = new ArrayList<>();
		List<InsuranceReplaceParam> replaceParamList = new ArrayList<>();
		if (!addParamList.isEmpty()) {
			R<List<InsuranceAddParam>> listR = detailService.addInsurance(addParamList,null);
			if (Common.isNotNull(listR) && !listR.getData().isEmpty()) {
				paramList = listR.getData();
			}
		}
		if (!batchAddParamList.isEmpty()) {
			R<List<InsuranceBatchParam>> listR = detailService.batchInsurance(batchAddParamList,null);
			if (Common.isNotNull(listR) && !listR.getData().isEmpty()) {
				batchParamList = listR.getData();
			}
		}
		if (!replaceAddParamList.isEmpty()) {
			R<List<InsuranceReplaceParam>> listR = detailService.replaceInsurance(replaceAddParamList,null);
			if (Common.isNotNull(listR) && !listR.getData().isEmpty()) {
				replaceParamList = listR.getData();
			}
		}
		// 使用Stream合并三个列表
		List<InsuranceAutoParam> autoAddParamList = Stream.concat(
				paramList.stream().map(this::convertAddParam),
				Stream.concat(
						batchParamList.stream().map(this::convertBatchParam),
						replaceParamList.stream().map(this::convertReplaceParam)
				)
		).collect(Collectors.toList());
		return R.ok(autoAddParamList);
	}

	@Override
	@Transactional
	public Boolean saveInsurancePreInfo(EmployeeRegistrationPreVo registrationPreVo) {
		List<TEmployeeInsurancePreVo> employeeInsurancePreVos = registrationPreVo.getEmployeeInsurancePreVos();
		TEmployeeInsurancePre preExit;
		if (null != employeeInsurancePreVos && !employeeInsurancePreVos.isEmpty()) {
			for (TEmployeeInsurancePreVo preVo : employeeInsurancePreVos) {
				//判断是否存在商险待购买信息
				preExit = baseMapper.selectOne(Wrappers.<TEmployeeInsurancePre>query().lambda()
						.eq(TEmployeeInsurancePre::getEmpIdcard, preVo.getEmpIdcard())
						.eq(TEmployeeInsurancePre::getDeptNo, preVo.getDeptNo())
						.eq(TEmployeeInsurancePre::getBuyType, preVo.getBuyType())
						.last(CommonConstants.LAST_ONE_SQL));
				TEmployeeInsurancePre pre = new TEmployeeInsurancePre();
				BeanUtils.copyProperties(preVo, pre);
				if (Common.isNotNull(preVo.getExpectedCollectionTime())) {
					pre.setExpectedCollectionTime(LocalDateTimeUtils.dateToLocalDateTime(preVo.getExpectedCollectionTime()));
				}
				if (Common.isNotNull(preExit)) {
					pre.setId(preExit.getId());
					baseMapper.insert(pre);
					baseMapper.deleteById(preExit);
					//todo 操作记录
				} else {
					baseMapper.insert(pre);
					if (Common.isNotNull(pre.getExpectedCollectionTime())) {
						// 事务提交后触发调度
						TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
							@Override
							public void afterCommit() {
								LocalDateTime now = LocalDateTime.now();
								if (pre.getExpectedCollectionTime().isEqual(now)) {
									scheduleService.executeTask(pre.getId());
								} else if (preVo.getExpectedCollectionTime().compareTo(LocalDateTimeUtils.convertLDTToDate(now)) > 0){
									scheduleService.scheduleTask(pre);
								}
							}
						});
					}
				}
			}
		}
		return true;
	}

	@Override
	public void saveInsurancePreInfo(String id, String status) {
		if (Common.isNotNull(id) && Common.isNotNull(status)) {
			TEmployeeInsurancePre preExit = baseMapper.selectById(id);
			if (Common.isNotNull(preExit)) {
				preExit.setProcessStatus(status);
				baseMapper.updateById(preExit);
			}
		}
	}

	/**
	 * @Description: 获取前端客服的所有项目权限
	 * @Author: huych
	 * @Date: 2025/3/13 17:02
	 * @return:
	 **/
	public void initSearchVo(TEmployeeInsurancePreSearchVo searchVo) {
		YifuUser user = SecurityUtils.getUser();
		long roleId = 1839501715787390978L;
		boolean isSsc = this.haveRole(user, roleId);
		if (isSsc || CommonConstants.ZERO_STRING.equals(user.getSystemFlag())) {
			searchVo.setAuthSql(null);
			return;
		}
		if (Common.isNotNull(searchVo.getType()) && CommonConstants.ONE_STRING.equals(searchVo.getType())) {
			searchVo.setAuthSql(null);
			//获取项目信息
			R<TSettleDomainRegistListVo> domainR = archivesDaprUtil.getAllDeptByCustomerLoginName(user.getUsername());
			if (null != domainR && null != domainR.getData() && null != domainR.getData().getDeptNos() && !domainR.getData().getDeptNos().isEmpty()) {
				searchVo.setDeptNoList(domainR.getData().getDeptNos());
			} else {
				searchVo.setId(CommonConstants.ONE_STRING_NEGATE);
			}
		}
	}

	public boolean haveRole(YifuUser user, long roleId) {
		List<Long> roleList = user.getClientRoleMap().get(ClientNameConstants.CLIENT_MVP);
		for (Long role : roleList) {
			if (role == roleId) {
				return true;
			}
		}
		return false;
	}

	private InsuranceAutoParam convertAddParam(InsuranceAddParam addParam) {
		InsuranceAutoParam autoParam = new InsuranceAutoParam();
		// 复制InsuranceAddParam的字段
		autoParam.setEmpName(addParam.getEmpName());
		autoParam.setEmpIdcardNo(addParam.getEmpIdcardNo());
		autoParam.setDeptNo(addParam.getDeptNo());
		autoParam.setInsuranceCompanyName(addParam.getInsuranceCompanyName());
		autoParam.setInsuranceTypeName(addParam.getInsuranceTypeName());
		autoParam.setPolicyStart(LocalDateUtil.parseLocalDate(addParam.getPolicyStart()));
		autoParam.setPolicyEnd(LocalDateUtil.parseLocalDate(addParam.getPolicyEnd()));
		autoParam.setBuyStandard(addParam.getBuyStandard());
		autoParam.setInsuranceProvinceName(addParam.getInsuranceProvinceName());
		autoParam.setInsuranceCityName(addParam.getInsuranceCityName());
		autoParam.setSettleMonth(addParam.getSettleMonth());
		autoParam.setPost(addParam.getPost());
		autoParam.setRemark(addParam.getRemark());
		return autoParam;
	}

	private InsuranceAutoParam convertBatchParam(InsuranceBatchParam batchParam) {
		InsuranceAutoParam autoParam = new InsuranceAutoParam();
		// 复制InsuranceBatchParam的字段
		autoParam.setEmpName(batchParam.getEmpName());
		autoParam.setEmpIdcardNo(batchParam.getEmpIdcardNo());
		autoParam.setDeptNo(batchParam.getDeptNo());
		autoParam.setInsuranceCompanyName(batchParam.getInsuranceCompanyName());
		autoParam.setInsuranceTypeName(batchParam.getInsuranceTypeName());
		autoParam.setPolicyNo(batchParam.getPolicyNo());
		autoParam.setBuyStandard(batchParam.getBuyStandard());
		autoParam.setInsuranceProvinceName(batchParam.getInsuranceProvinceName());
		autoParam.setInsuranceCityName(batchParam.getInsuranceCityName());
		autoParam.setSettleMonth(batchParam.getSettleMonth());
		autoParam.setPost(batchParam.getPost());
		autoParam.setRemark(batchParam.getRemark());
		return autoParam;
	}

	private InsuranceAutoParam convertReplaceParam(InsuranceReplaceParam replaceParam) {
		InsuranceAutoParam autoParam = new InsuranceAutoParam();
		// 复制InsuranceReplaceParam的字段
		autoParam.setEmpName(replaceParam.getEmpName());
		autoParam.setEmpIdcardNo(replaceParam.getEmpIdcardNo());
		autoParam.setDeptNo(replaceParam.getDeptNo());
		autoParam.setInsuranceCompanyName(replaceParam.getInsuranceCompanyName());
		autoParam.setInsuranceTypeName(replaceParam.getInsuranceTypeName());
		autoParam.setBuyStandard(replaceParam.getBuyStandard());
		autoParam.setPolicyStart(LocalDateUtil.parseLocalDate(replaceParam.getPolicyStart()));
		autoParam.setPolicyEnd(LocalDateUtil.parseLocalDate(replaceParam.getPolicyEnd()));
		autoParam.setPost(replaceParam.getPost());
		autoParam.setReplaceEmpName(replaceParam.getReplaceEmpName());
		autoParam.setReplaceDeptNo(replaceParam.getReplaceDeptNo());
		autoParam.setReplaceEmpIdcardNo(replaceParam.getReplaceEmpIdcardNo());
		return autoParam;
	}

}
