
package org.sky.scientific.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.sky.core.log.exception.ServiceException;
import org.sky.core.mp.base.BaseServiceImpl;
import org.sky.core.secure.utils.SecureUtil;
import org.sky.core.tool.utils.CollectionUtil;
import org.sky.core.tool.utils.Func;
import org.sky.core.tool.utils.StringUtil;
import org.sky.scientific.excel.XmAssetHoursExcel;
import org.sky.scientific.excel.XmAssetHoursListener;
import org.sky.scientific.mapper.AssetMapper;
import org.sky.scientific.mapper.XmAssetHoursMapper;
import org.sky.scientific.mapper.XmMapper;
import org.sky.scientific.pojo.dto.XmAssetHoursDto;
import org.sky.scientific.pojo.entity.AssetEntity;
import org.sky.scientific.pojo.entity.XmAssetHoursEntity;
import org.sky.scientific.pojo.vo.DailyAttendance;
import org.sky.scientific.pojo.vo.XmAssetHoursVO;
import org.sky.scientific.service.IXmAssetHoursService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedInputStream;
import java.time.YearMonth;
import java.util.*;

/**
 * 科研仪器设备工时 服务实现类
 *
 * @author Kd
 * @since 2025-06-29
 */
@Slf4j
@Service
public class XmAssetHoursServiceImpl extends BaseServiceImpl<XmAssetHoursMapper, XmAssetHoursEntity> implements IXmAssetHoursService {

	@Resource
	private XmMapper xmMapper;

	@Resource
	private AssetMapper assetMapper;

	@SneakyThrows
	@Transactional(rollbackFor = Exception.class)
	@Override
	public void importXmAssetHours(MultipartFile file, String yearAndMonth) {
		XmAssetHoursListener listener = new XmAssetHoursListener();
		listener.setYearAndMonth(yearAndMonth);
		EasyExcel.read(new BufferedInputStream(file.getInputStream()))
			.registerReadListener(listener)
			.sheet(0)
			.headRowNumber(3) // 重要：设置表头行数(0-based)
			.doRead();
		List<XmAssetHoursExcel> records = listener.getRecords();
		if (CollectionUtil.isEmpty(records)) {
			throw new ServiceException("未能从模板中读取数据，请检查模板格式是否正确");
		}

		//需要新增的，以便后续批量新增
		List<XmAssetHoursEntity> insertList = new ArrayList<>();
		//需要更新的，以便后续批量修改
		List<XmAssetHoursEntity> updateList = new ArrayList<>();

		int batchCount = 20;

		List<XmAssetHoursEntity> dbList = baseMapper.selectByYearAndMonth(yearAndMonth, null, null);
		for (XmAssetHoursExcel record : records) {
			//保存
			if(StringUtil.isAllBlank(record.getXmmc(), record.getXmbh())){
				throw new ServiceException("研发项目编号、研发项目名称都为空，请检查数据");
			}
			Long xmId = xmMapper.getXmIdByXmmcOrXmbh(yearAndMonth, record.getXmmc(), record.getXmbh());
			if (xmId == null) {
				throw new ServiceException("序号为[" + record.getSerialNumber() + "]的研发项目编号和研发项目名称都不存在");
			}

			if(StringUtil.isBlank(record.getZcbm())){
				throw new ServiceException("序号为[" + record.getSerialNumber() + "]的资产编码为空");
			}
			AssetEntity dbAsset = assetMapper.selectOne(Wrappers.<AssetEntity>lambdaQuery().eq(AssetEntity::getZcbm, record.getZcbm()).eq(AssetEntity::getYearAndMonth, yearAndMonth));
			if (null == dbAsset) {
				throw new ServiceException("序号为[" + record.getSerialNumber() + "]的资产不存在");
			}
			List<XmAssetHoursEntity> byXmAndAssetList = dbList.stream().filter(e -> e.getXmId().equals(xmId) && e.getAssetId().equals(dbAsset.getId())).toList();
			for (DailyAttendance dailyAttendance : record.getDailyAttendances()) {

				List<Long> primaryKeyList = byXmAndAssetList.stream().filter(e -> Objects.equals(e.getWorkDate(), dailyAttendance.getWorkDate())).map(XmAssetHoursEntity::getId).toList();
				Long primaryKey = CollectionUtil.isEmpty(primaryKeyList) ? null : primaryKeyList.get(0);
				XmAssetHoursEntity entity = new XmAssetHoursEntity();
				if (primaryKey == null) {
					entity.setXmId(xmId);
					entity.setAssetId(dbAsset.getId());
					entity.setWorkDate(dailyAttendance.getWorkDate());
					entity.setWorkHours(dailyAttendance.getWorkHours());
					entity.setTenantId(SecureUtil.getTenantId());
					entity.setCreateUser(SecureUtil.getUserId());
					entity.setCreateDept(Func.toLong(SecureUtil.getDeptId()));
					insertList.add(entity);
				} else {
					entity.setId(primaryKey);
					entity.setWorkHours(dailyAttendance.getWorkHours());
					updateList.add(entity);
				}
				if (!insertList.isEmpty() && insertList.size() % batchCount == 0) {
					int insertCount = baseMapper.batchInsert(insertList);
					if (insertCount == batchCount) {
						insertList.clear();
					}

				}
				if (!updateList.isEmpty() && updateList.size() % batchCount == 0) {
					int updateCount = baseMapper.batchUpdate(updateList);
					if (updateCount == batchCount) {
						updateList.clear();
					}
				}
			}
		}
		if (!insertList.isEmpty()) {
			baseMapper.batchInsert(insertList);
		}
		if (!updateList.isEmpty()) {
			baseMapper.batchUpdate(updateList);
		}
	}

	@Override
	public IPage<XmAssetHoursVO> selectXmAssetHoursPage(XmAssetHoursDto dto, IPage<XmAssetHoursVO> page) {
		if (StringUtil.isBlank(dto.getYearAndMonth())) {
			throw new ServiceException("参数yearAndMonth不能为空");
		}
		List<XmAssetHoursVO> list = baseMapper.selectXmAssetHoursPage(page, dto);
		for (XmAssetHoursVO temp : list) {
			List<DailyAttendance> dailyAttendanceList = baseMapper.selectHoursByXmIdAndAssetId(temp.getXmId(), temp.getAssetId(), dto.getYearAndMonth());
			if(CollectionUtil.isEmpty(dailyAttendanceList)){
				continue;
			}
			temp.setDailyAttendances(dailyAttendanceList);
		}
		return page.setRecords(list);
	}

	@Override
	public boolean batchSubmitXmAssetHours(XmAssetHoursDto dto) {
		if (StringUtil.isBlank(dto.getYearAndMonth())) {
			throw new ServiceException("参数yearAndMonth不能为空");
		}
		if(dto.getXmId()==null){
			throw new ServiceException("参数xmId不能为空");
		}
		if(dto.getAssetId()==null){
			throw new ServiceException("参数assetId不能为空");
		}

		AssetEntity dbAsset = assetMapper.selectById(dto.getAssetId());
		if(Func.isEmpty(dbAsset)){
			throw new ServiceException("资产不存在");
		}

		if (dto.getZgs() != null) {

			//不能大于当月工作天数（自然天数）X24小时
			// 解析年份和月份
			int year = Integer.parseInt(dto.getYearAndMonth().substring(0, 4));
			int month = Integer.parseInt(dto.getYearAndMonth().substring(4));

			// 获取YearMonth对象并得到天数
			YearMonth yearMonth = YearMonth.of(year, month);
			int days = yearMonth.lengthOfMonth();
			if (dto.getZgs() > days * 24) {
				throw new ServiceException("总工时不能大于当月工作天数X24小时");
			}

			//总工时未填，且两次工时不一致
//			if(dbAsset.getZgs()!=null && !Objects.equals(dbAsset.getZgs(),dto.getZgs())){
//				throw new ServiceException("该资产在["+dto.getYearAndMonth()+"]已有总工时["+dbAsset.getZgs()+"]");
//			}

			dbAsset.setZgs(dto.getZgs());
			assetMapper.updateById(dbAsset);
		}

		List<XmAssetHoursEntity> dbList = baseMapper.selectByYearAndMonth(dto.getYearAndMonth(), dto.getXmId(), dto.getAssetId());

		//需要新增的，以便后续批量新增
		List<XmAssetHoursEntity> insertList = new ArrayList<>();
		//需要更新的，以便后续批量修改
		List<XmAssetHoursEntity> updateList = new ArrayList<>();

		for (DailyAttendance dailyAttendance : dto.getDailyHoursList()) {

			List<Long> primaryKeyList = dbList.stream().filter(e -> Objects.equals(e.getWorkDate(), dailyAttendance.getWorkDate())).map(XmAssetHoursEntity::getId).toList();
			Long primaryKey = CollectionUtil.isEmpty(primaryKeyList) ? null : primaryKeyList.get(0);
			XmAssetHoursEntity entity = new XmAssetHoursEntity();
			if (primaryKey == null) {
				entity.setXmId(dto.getXmId());
				entity.setAssetId(dto.getAssetId());
				entity.setWorkDate(dailyAttendance.getWorkDate());
				entity.setWorkHours(dailyAttendance.getWorkHours());
				entity.setTenantId(SecureUtil.getTenantId());
				entity.setCreateUser(SecureUtil.getUserId());
				entity.setCreateDept(Func.toLong(SecureUtil.getDeptId()));
				insertList.add(entity);
			} else {
				entity.setId(primaryKey);
				entity.setWorkHours(dailyAttendance.getWorkHours());
				updateList.add(entity);
			}
		}

		if (!insertList.isEmpty()) {
			baseMapper.batchInsert(insertList);
			insertList.clear();
		}
		if (!updateList.isEmpty()) {
			baseMapper.batchUpdate(updateList);
			updateList.clear();
		}
		return true;
	}

	@Override
	public boolean clearXmAssetHours(JSONObject dto) {
		JSONArray xmAndAssetIdList = dto.getJSONArray("xmAndAssetIdList");
		if (xmAndAssetIdList == null || xmAndAssetIdList.isEmpty()) {
			throw new ServiceException("参数xmAndAssetIdList不能为空");
		}
		for (Object xmAndAssetId : xmAndAssetIdList) {
			Map<String, String> map =(HashMap<String,String>) xmAndAssetId;
			baseMapper.clearXmAssetHours(dto.getString("yearAndMonth"),Long.valueOf(map.get("xmId")), Long.valueOf(map.get("assetId")));
		}
		return true;
	}
}
