
package org.sky.scientific.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import org.sky.core.excel.util.ExcelUtil;
import org.sky.core.log.exception.ServiceException;
import org.sky.core.mp.base.BaseServiceImpl;
import org.sky.core.mp.support.Condition;
import org.sky.core.mp.support.Query;
import org.sky.core.tool.utils.*;
import org.sky.scientific.excel.SalaryExcel;
import org.sky.scientific.mapper.SalaryMapper;
import org.sky.scientific.mapper.TechnicianMapper;
import org.sky.scientific.mapper.XmTechnicianMapper;
import org.sky.scientific.pojo.dto.SalaryDTO;
import org.sky.scientific.pojo.entity.SalaryEntity;
import org.sky.scientific.pojo.entity.TechnicianEntity;
import org.sky.scientific.pojo.entity.XmTechnicianEntity;
import org.sky.scientific.pojo.vo.SalaryVO;
import org.sky.scientific.service.ISalaryService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 每月工资信息 服务实现类
 *
 * @author Kd
 * @since 2025-06-19
 */
@Service
public class SalaryServiceImpl extends BaseServiceImpl<SalaryMapper, SalaryEntity> implements ISalaryService {

	@Resource
	private TechnicianMapper technicianMapper;
	@Resource
	private XmTechnicianMapper xmTechnicianMapper;

	@Override
	public IPage<SalaryVO> selectSalaryPage(IPage<SalaryVO> page, SalaryDTO salary) {
		if(StringUtil.isBlank(salary.getYearAndMonth())){
			throw new ServiceException("参数yearAndMonth不能为空");
		}
		List<SalaryVO> voList = baseMapper.selectSalaryPage(page, salary);

		return page.setRecords(voList);
	}


	@SneakyThrows
	@Override
	public void exportSalary(HttpServletResponse response, SalaryDTO dto){

		Query query = new Query().setCurrent(1).setSize(Integer.MAX_VALUE);
		List<SalaryVO> assetVOList = this.selectSalaryPage(Condition.getPage(query), dto).getRecords();

		AtomicInteger i = new AtomicInteger(1);
 		assetVOList.forEach(temp -> {
			temp.setXh(i.getAndIncrement()+"");
			temp.setTotal(temp.getPensionInsurance().add(temp.getMedicalInsurance()).add(temp.getUnemploymentInsurance()).add(temp.getInjuryInsurance()).add(temp.getMaternityInsurance()));
		});

		InputStream templateFileName = this.getClass().getClassLoader().getResourceAsStream("export-template/每月工资信息.xls");
		response.setContentType("application/vnd.ms-excel");
		response.setCharacterEncoding("utf-8");
		response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("每月工资信息.xls", Charsets.UTF_8));
		ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
			.withTemplate((templateFileName))
			.excelType(ExcelTypeEnum.XLS)
			.build();

		WriteSheet writeSheet = EasyExcel.writerSheet().build();
		//设置list集合数据
		excelWriter.fill(assetVOList, writeSheet);
		Map<String,Object> map = new HashMap<>();
		map.put("year", dto.getYearAndMonth().substring(0,4));
		map.put("month", dto.getYearAndMonth().substring(4));
		excelWriter.fill(map, writeSheet);
		excelWriter.finish();
		if (templateFileName != null) {
			templateFileName.close();
		}
	}

	@Override
	public boolean updateSalary(SalaryEntity salary) {
		boolean result = false;
		//根据number、identityId、yearAndMonth查询工资数据，
		LambdaQueryWrapper<SalaryEntity> queryWrapper = Wrappers.<SalaryEntity>lambdaQuery()
			.eq(SalaryEntity::getUnicode, salary.getUnicode())
			.eq(SalaryEntity::getYearAndMonth, salary.getYearAndMonth());
		if (baseMapper.selectCount(queryWrapper) == 1) {
			//存在，则修改
			if(Func.isAllEmpty(salary.getAverageMonthlySalary(), salary.getPensionInsurance(), salary.getMedicalInsurance(), salary.getUnemploymentInsurance(), salary.getInjuryInsurance(), salary.getMaternityInsurance(), salary.getProvidentFund(), salary.getBonus(), salary.getBenefit(), salary.getPensionInsuranceBc(), salary.getMedicalInsuranceBc())){
//				throw new ServiceException("数据无更新");
				return true;
			}
			result = baseMapper.updateSalary(salary) == 1;
		} else {
			//不存在，则新增
			if (salary.getAverageMonthlySalary() != null) {
				salary.setAverageMonthlySalaryEdit(1);
			}
			if (salary.getPensionInsurance() != null) {
				salary.setPensionInsuranceEdit(1);
			}
			if (salary.getMedicalInsurance() != null) {
				salary.setMedicalInsuranceEdit(1);
			}
			if (salary.getUnemploymentInsurance() != null) {
				salary.setUnemploymentInsuranceEdit(1);
			}
			if (salary.getInjuryInsurance() != null) {
				salary.setInjuryInsuranceEdit(1);
			}
			if (salary.getMaternityInsurance() != null) {
				salary.setMaternityInsuranceEdit(1);
			}
			if (salary.getProvidentFund() != null) {
				salary.setProvidentFundEdit(1);
			}
			if (salary.getBonus() != null) {
				salary.setBonusEdit(1);
			}
			if (salary.getBenefit() != null) {
				salary.setBenefitEdit(1);
			}
			if (salary.getPensionInsuranceBc() != null) {
				salary.setPensionInsuranceBcEdit(1);
			}
			if (salary.getMedicalInsuranceBc() != null) {
				salary.setMedicalInsuranceBcEdit(1);
			}
			result = this.save(salary);
		}
		return result;
	}

	@Override
	public boolean clearSalary(List<SalaryEntity> salaryList) {
		int affectNum = 0;
		//根据unicode、yearAndMonth工资数据
		for (SalaryEntity salary : salaryList) {
			affectNum += baseMapper.clearSalary(salary);
		}
		return true;
	}

	@Override
	public boolean fetchTechnicianByYearAndMonth(String yearAndMonth) {
		//查询yearAndMonth的实际参研人员名单
		List<XmTechnicianEntity> list = xmTechnicianMapper.selectList(Wrappers.<XmTechnicianEntity>lambdaQuery().eq(XmTechnicianEntity::getYearAndMonth, yearAndMonth));
		if(CollectionUtil.isEmpty(list)){
			throw new ServiceException("该月份无实际参研人员");
		}
		List<String> unicodeList = list.stream().map(XmTechnicianEntity::getUnicode).distinct().toList();
		//yearAndMonth已有工资数据的研发人员
		List<SalaryEntity> salaryEntities = baseMapper.selectList(Wrappers.<SalaryEntity>lambdaQuery().eq(SalaryEntity::getYearAndMonth, yearAndMonth));
		List<String> dbUnicodeList = null;
		if(CollectionUtil.isNotEmpty(salaryEntities)){
			dbUnicodeList = salaryEntities.stream().map(SalaryEntity::getUnicode).toList();
			List<String> finalDbUnicodeList = dbUnicodeList;
			unicodeList = unicodeList.stream().filter(n -> !finalDbUnicodeList.contains(n)).toList();
		}

		List<SalaryEntity> insertList = new ArrayList<>();
		for (String unicode : unicodeList) {
			SalaryEntity salary = new SalaryEntity();
			salary.setUnicode(unicode);
			salary.setYearAndMonth(yearAndMonth);
			insertList.add(salary);
		}
		if (CollectionUtil.isNotEmpty(unicodeList)) {
			return this.saveBatch(insertList);
		}
		return true;
	}

	@Transactional
	@Override
	public void importSalary(MultipartFile file, String yearAndMonth) {
		if(StringUtil.isBlank(yearAndMonth) || yearAndMonth.length() != 6){
			throw new ServiceException("请传入参数yearAndMonth，格式：YYYYmm");
		}
		List<SalaryExcel> data = ExcelUtil.read(file, 0, 2, SalaryExcel.class);
		if(CollectionUtil.isEmpty(data)){
			throw new ServiceException("未能从模板中读取数据，请检查模板格式是否正确");
		}
		//导入时人员非本月实际参研人员，提示“某某非本月实际参研人员，请核对数据”
		//获取本月实际参研人员名单
		List<XmTechnicianEntity> technicianByYearMonth = xmTechnicianMapper.selectList(Wrappers.<XmTechnicianEntity>lambdaQuery().eq(XmTechnicianEntity::getYearAndMonth, yearAndMonth));
		if(CollectionUtil.isEmpty(technicianByYearMonth)){
			throw new ServiceException(yearAndMonth+"实际参研人员名单为空");
		}
		List<String> unicodeList = technicianByYearMonth.stream().map(XmTechnicianEntity::getUnicode).toList();

		for (SalaryExcel excel : data) {
			if(StringUtil.isAllBlank(excel.getNumber(), excel.getIdCard())){
				throw new ServiceException("序号为["+excel.getXh()+"]的工号和身份证不能都为空");
			}
			//根据工号或者身份证查询technicianId
			LambdaQueryWrapper<TechnicianEntity> wrapper = Wrappers.<TechnicianEntity>lambdaQuery()
				.eq(TechnicianEntity::getYearAndMonth, yearAndMonth)
				.and(t -> t.eq(TechnicianEntity::getNumber, excel.getNumber()).or().eq(TechnicianEntity::getIdCard, excel.getIdCard()));
			TechnicianEntity dbTechnician = technicianMapper.selectOne(wrapper);
			if(dbTechnician == null){
				throw new ServiceException("序号为["+excel.getXh()+"]的工号和者身份证都不存在");
			}

			//非本月实际参研人员，提示“某某非本月实际参研人员，请核对数据”
			if(!unicodeList.contains(dbTechnician.getUnicode())){
				String tips = StringUtil.isNoneBlank(excel.getNumber())?excel.getNumber()+","+excel.getIdCard():excel.getIdCard();
				throw new ServiceException("人员["+tips+"]非本月实际参研人员，请核对数据");
			}

			LambdaQueryWrapper<SalaryEntity> queryWrapper = Wrappers.<SalaryEntity>lambdaQuery()
				.eq(SalaryEntity::getYearAndMonth, yearAndMonth)
				.eq(SalaryEntity::getUnicode, dbTechnician.getUnicode());
			if(baseMapper.selectCount(queryWrapper) > 0){
				throw new ServiceException("序号为["+excel.getXh()+"]的工资数据已存在, 导入失败");
			}

			SalaryEntity entity = Objects.requireNonNull(BeanUtil.copyProperties(excel, SalaryDTO.class));
			entity.setUnicode(dbTechnician.getUnicode());
			entity.setYearAndMonth(yearAndMonth);
			this.save(entity);
		}
	}
}
