/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the yifu4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */
package com.yifu.cloud.plus.v1.yifu.archives.service.impl;

import cn.hutool.core.util.ArrayUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
import com.alibaba.excel.util.ListUtils;
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 com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yifu.cloud.plus.v1.yifu.archives.entity.TFascEditLog;
import com.yifu.cloud.plus.v1.yifu.archives.entity.TFascTemplate;
import com.yifu.cloud.plus.v1.yifu.archives.entity.TFascTemplateDetail;
import com.yifu.cloud.plus.v1.yifu.archives.mapper.TFascTemplateDetailMapper;
import com.yifu.cloud.plus.v1.yifu.archives.mapper.TFascTemplateMapper;
import com.yifu.cloud.plus.v1.yifu.archives.service.TFascEditLogService;
import com.yifu.cloud.plus.v1.yifu.archives.service.TFascHrFieldService;
import com.yifu.cloud.plus.v1.yifu.archives.service.TFascTemplateDetailService;
import com.yifu.cloud.plus.v1.yifu.archives.utils.FascConstants;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TFascTemplateDetailExportVo;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TFascTemplateDetailSearchVo;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TFascTemplateDetailUpdateVo;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.util.*;
import com.yifu.cloud.plus.v1.yifu.common.mybatis.base.BaseEntity;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;

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

/**
 * 法大大专业版模板映射表
 *
 * @author hgw
 * @date 2025-09-30 16:29:28
 */
@Log4j2
@Service
@RequiredArgsConstructor
public class TFascTemplateDetailServiceImpl extends ServiceImpl<TFascTemplateDetailMapper, TFascTemplateDetail> implements TFascTemplateDetailService {

	private final TFascEditLogService tFascEditLogService;
	private final TFascHrFieldService tFascHrFieldService;
	private final TFascTemplateMapper tFascTemplateMapper;

	/**
	 * 法大大专业版模板映射表简单分页查询
	 *
	 * @param tFascTemplateDetail 法大大专业版模板映射表
	 * @return
	 */
	@Override
	public IPage<TFascTemplateDetail> getTFascTemplateDetailPage(Page<TFascTemplateDetail> page, TFascTemplateDetailSearchVo tFascTemplateDetail) {
		return baseMapper.getTFascTemplateDetailPage(page, tFascTemplateDetail);
	}

	/**
	 * 法大大专业版模板映射表_发起专用，含格式化映射字段
	 *
	 * @param fadadaTemplateId 法大大专业版模板映射表
	 * @return
	 */
	@Override
	public List<TFascTemplateDetail> getTDetailListByFieldType(String fadadaTemplateId) {
		return baseMapper.getTDetailListByFieldType(fadadaTemplateId);
	}
	/**
	 * 法大大专业版模板映射表简单分页查询
	 *
	 * @param tFascTemplateDetail 法大大专业版模板映射表
	 * @return
	 */
	@Override
	public List<TFascTemplateDetail> getTFascTemplateDetailList(TFascTemplateDetail tFascTemplateDetail) {
		return baseMapper.getTFascTemplateDetailList(tFascTemplateDetail);
	}

	/**
	 * 法大大专业版模板映射表批量导出
	 *
	 * @param searchVo 法大大专业版模板映射表
	 * @return
	 */
	@Override
	public void listExport(HttpServletResponse response, TFascTemplateDetailSearchVo searchVo) {
		String fileName = "法大大字段映射关系表" + DateUtil.getThisTime() + ".xlsx";
		//获取要导出的列表
		List<TFascTemplateDetailExportVo> list = new ArrayList<>();
		List<String> idList = Common.getList(searchVo.getIds());
		long count = baseMapper.getTFascTemplateDetailExportCount(searchVo, idList);
		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, CommonConstants.UTF8));
			// 这里 需要指定写用哪个class去写，然后写到第一个sheet，然后文件流会自动关闭
			ExcelWriter excelWriter = EasyExcelFactory.write(out, TFascTemplateDetailExportVo.class).build();
			int index = 0;
			if (count > CommonConstants.ZERO_INT) {
				WriteSheet writeSheet;
				for (int i = 0; i <= count; i += CommonConstants.EXCEL_EXPORT_LIMIT) {
					// 获取实际记录
					searchVo.setLimitStart(i);
					searchVo.setLimitEnd(CommonConstants.EXCEL_EXPORT_LIMIT);
					list = baseMapper.getTFascTemplateDetailExport(searchVo, idList);
					if (Common.isNotNull(list)) {
						writeSheet = EasyExcelFactory.writerSheet("映射关系配置——列表字段" + index).build();
						excelWriter.write(list, writeSheet);
						index++;
					}
				}
			} else {
				WriteSheet writeSheet = EasyExcelFactory.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);
			}
		}
	}

	@Override
	public List<TFascTemplateDetail> noPageDiy(TFascTemplateDetailSearchVo searchVo) {
		LambdaQueryWrapper<TFascTemplateDetail> wrapper = buildQueryWrapper(searchVo);
		if (searchVo != null) {
			List<String> idList = Common.getList(searchVo.getIds());
			if (Common.isNotNull(idList)) {
				wrapper.in(TFascTemplateDetail::getId, idList);
			}
			if (searchVo.getLimitStart() >= 0 && searchVo.getLimitEnd() > 0) {
				wrapper.last(" limit " + searchVo.getLimitStart() + "," + searchVo.getLimitEnd());
			}
		}
		wrapper.orderByDesc(BaseEntity::getCreateTime);
		return baseMapper.selectList(wrapper);
	}

	private LambdaQueryWrapper buildQueryWrapper(TFascTemplateDetailSearchVo entity) {
		LambdaQueryWrapper<TFascTemplateDetail> wrapper = Wrappers.lambdaQuery();
		if (ArrayUtil.isNotEmpty(entity.getCreateTimes())) {
			wrapper.ge(TFascTemplateDetail::getCreateTime, entity.getCreateTimes()[0])
					.le(TFascTemplateDetail::getCreateTime,
							entity.getCreateTimes()[1]);
		}
		if (Common.isNotNull(entity.getCreateName())) {
			wrapper.eq(TFascTemplateDetail::getCreateName, entity.getCreateName());
		}
		return wrapper;
	}

	/**
	 * @Description: 获取模板，key是id与_与名称的组合
	 * @Author: hgw
	 * @Date: 2025/10/9 9:33
	 * @return: java.util.Map<java.lang.String, com.yifu.cloud.plus.v1.yifu.archives.entity.TFascTemplate>
	 **/
	private Map<String, TFascTemplateDetail> getTemplateDetailMap() {
		List<TFascTemplateDetail> list = baseMapper.getTFascTemplateDetailList(null);
		Map<String, TFascTemplateDetail> map = new HashMap<>();
		if (Common.isNotNull(list)) {
			for (TFascTemplateDetail t : list) {
				map.put(t.getSignTemplateId() + CommonConstants.DOWN_LINE_STRING + t.getSignTemplateName()
						+ CommonConstants.DOWN_LINE_STRING + t.getFascFieldId()
						+ CommonConstants.DOWN_LINE_STRING + t.getFascField(), t);
			}
		}
		return map;
	}

	@Override
	public R<List<ErrorMessage>> batchUpdateFascDetail(InputStream inputStream) {
		List<ErrorMessage> errorMessageList = new ArrayList<>();
		ExcelUtil<TFascTemplateDetailUpdateVo> util1 = new ExcelUtil<>(TFascTemplateDetailUpdateVo.class);
		Map<String, TFascTemplateDetail> templateDetailMap = this.getTemplateDetailMap();

		Map<String, Map<String, String>> fieldAllMap = tFascHrFieldService.getFieldAllMap(null);

		// 写法2：
		// 匿名内部类 不用额外写一个DemoDataListener
		// 这里 需要指定读用哪个class去读，然后读取第一个sheet 文件流会自动关闭
		try {
			EasyExcel.read(inputStream, TFascTemplateDetailUpdateVo.class, new ReadListener<TFascTemplateDetailUpdateVo>() {
				/**
				 * 单次缓存的数据量
				 */
				public static final int BATCH_COUNT = CommonConstants.BATCH_COUNT;
				/**
				 *临时存储
				 */
				private List<TFascTemplateDetailUpdateVo> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

				@Override
				public void invoke(TFascTemplateDetailUpdateVo data, AnalysisContext context) {
					ReadRowHolder readRowHolder = context.readRowHolder();
					Integer rowIndex = readRowHolder.getRowIndex();
					data.setRowIndex(rowIndex + 1);
					ErrorMessage errorMessage = util1.checkEntity(data, data.getRowIndex());
					if (Common.isNotNull(errorMessage)) {
						errorMessage.setData(data);
						errorMessageList.add(errorMessage);
					} else {
						cachedDataList.add(data);
					}
					if (cachedDataList.size() >= BATCH_COUNT) {
						saveData();
						// 存储完成清理 list
						cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
					}
				}

				@Override
				public void doAfterAllAnalysed(AnalysisContext context) {
					saveData();
				}

				/**
				 * 加上存储数据库
				 */
				private void saveData() {
					log.info("{}条数据，开始存储数据库！", cachedDataList.size());
					updateTFascTemplate(cachedDataList, errorMessageList, templateDetailMap, fieldAllMap);
					log.info("存储数据库成功！");
				}
			}).sheet().doRead();
		} catch (Exception e) {
			log.error(CommonConstants.IMPORT_DATA_ANALYSIS_ERROR, e);
			return R.failed(CommonConstants.IMPORT_DATA_ANALYSIS_ERROR);
		}
		// 重新计算模板的是否已配置——放到循环外面了
		this.initFascTemplateIsMust(null);

		for (ErrorMessage message : errorMessageList) {
			if (!CommonConstants.SAVE_SUCCESS.equals(message.getMessage())) {
				return R.ok(errorMessageList);
			}
		}
		return R.ok();
	}

	private void updateTFascTemplate(List<TFascTemplateDetailUpdateVo> excelVOList, List<ErrorMessage> errorMessageList
			, Map<String, TFascTemplateDetail> templateDetailMap, Map<String, Map<String, String>> fieldAllMap) {
		TFascTemplateDetailUpdateVo excel;
		TFascTemplateDetail tUpdate;
		List<TFascTemplateDetail> tempUpdateList = new ArrayList<>();
		List<TFascEditLog> logList = new ArrayList<>();
		TFascEditLog tFascEditLog;
		String editContent;
		Map<String, String> fieldMap;
		for (int i = 0; i < excelVOList.size(); i++) {
			excel = excelVOList.get(i);
			if (Common.isEmpty(excel.getHrField()) || Common.isEmpty(excel.getHrFieldId())) {
				errorMessageList.add(new ErrorMessage(excel.getRowIndex(), "对应皖信字段、对应皖信字段ID不可为空", excel));
			} else {
				tUpdate = templateDetailMap.get(excel.getSignTemplateId()
						+ CommonConstants.DOWN_LINE_STRING + excel.getSignTemplateName()
						+ CommonConstants.DOWN_LINE_STRING + excel.getFascFieldId()
						+ CommonConstants.DOWN_LINE_STRING + excel.getFascField());
				if (tUpdate == null) {
					errorMessageList.add(new ErrorMessage(excel.getRowIndex(), "根据法大大模版名称、模版ID、法大大字段、法大大字段ID，未找到映射关系", excel));
				} else if (Common.isEmpty(tUpdate.getContractType())) {
					errorMessageList.add(new ErrorMessage(excel.getRowIndex(), "该法大大模版无合同类型，请先配置模板", excel));
				} else {
					fieldMap = fieldAllMap.get(tUpdate.getContractType());
					if (fieldMap == null) {
						errorMessageList.add(new ErrorMessage(excel.getRowIndex(), "该合同类型“"
								+ tUpdate.getContractType() + "”无字段配置，请联系管理员配置表TFascHrField", excel));
					} else {
						if (fieldMap.get(excel.getHrFieldId() + CommonConstants.DOWN_LINE_STRING + excel.getHrField()) == null) {
							errorMessageList.add(new ErrorMessage(excel.getRowIndex(), "该合同类型下，未找到皖信字段", excel));
						} else {
							// 真正的更新：
							tFascEditLog = new TFascEditLog();
							tFascEditLog.setMainId(tUpdate.getId());
							tFascEditLog.setMainType(CommonConstants.TWO_STRING);
							if (excel.getHrField().equals(tUpdate.getHrField()) && excel.getHrFieldId().equals(tUpdate.getHrFieldId())) {
								editContent = "“皖信字段”由“" + tUpdate.getHrField() + "”→“" + excel.getHrField() + "”";
							} else {
								if (Common.isEmpty(tUpdate.getHrFieldId())) {
									editContent = "“皖信字段”由“空”→“" + excel.getHrField() + "”";
								} else {
									editContent = "“皖信字段”由“" + tUpdate.getHrField() + "”→“" + excel.getHrField() + "”";
								}
								tUpdate.setHrField(excel.getHrField());
								tUpdate.setHrFieldId(excel.getHrFieldId());
								if (Common.isEmpty(tUpdate.getIsEdit()) || tUpdate.getIsEdit().equals(CommonConstants.ZERO_STRING)) {
									tUpdate.setIsEdit(CommonConstants.ONE_STRING);
									editContent += "；“是否已配置”由“未配置”→“已配置”";
								}
								// 添加到更新list
								tempUpdateList.add(tUpdate);
							}
							tFascEditLog.setEditContent(editContent);
							logList.add(tFascEditLog);
							errorMessageList.add(new ErrorMessage(excel.getRowIndex(), CommonConstants.SAVE_SUCCESS));
						}
					}
				}
			}
		}
		if (!tempUpdateList.isEmpty()) {
			this.updateBatchById(tempUpdateList);
		}
		if (!logList.isEmpty()) {
			tFascEditLogService.saveBatch(logList);
		}
		// 重新计算模板的是否已配置——放到循环外面了
	}

	@Override
	public void initDetailHrField(String templateId) {
		List<TFascTemplateDetail> detailList = baseMapper.getDetailByHaveHrField(templateId);
		if (detailList != null && !detailList.isEmpty()) {
			List<TFascEditLog> logList = new ArrayList<>();
			TFascEditLog logs;
			for (TFascTemplateDetail detail : detailList) {
				logs = new TFascEditLog();
				logs.setMainId(detail.getId());
				logs.setMainType(CommonConstants.TWO_STRING);
				logs.setEditContent("“皖信字段”由“"+detail.getHrField()+"”→“空”；“是否已配置”由“已配置”→“未配置”");
				logList.add(logs);
			}
			// 初始化皖信字段、是否已配置
			baseMapper.initDetailHrField(templateId);
			// 保存日志
			tFascEditLogService.saveBatch(logList);
			// 更新模板的是否已配置
			this.initFascTemplateIsMust(templateId);
		}
	}
	@Override
	public R<String> initFascTemplateIsMust(String templateId) {
		// 先查找：
		List<TFascTemplate> tFascTemplateList = tFascTemplateMapper.getTFascTemplateResutList(templateId);
		if (tFascTemplateList != null && !tFascTemplateList.isEmpty()) {
			List<TFascTemplate> updateList = new ArrayList<>();
			List<TFascEditLog> logList = new ArrayList<>();
			TFascEditLog tFascEditLog;
			String editContent;
			// 0未配置1部分配置2已配置
			String isMustEditNew;
			for (TFascTemplate t : tFascTemplateList) {
				// 改变的，需要更新
				if (Common.isNotNull(t.getIsMustEdit()) && Common.isNotNull(t.getIsMustAll()) && Common.isNotNull(t.getIsMustNow())) {
					// 如果必填项没了，则默认为已配置
					if (CommonConstants.ZERO_STRING.equals(t.getIsMustAll()) || t.getIsMustAll().equals(t.getIsMustNow())) {
						isMustEditNew = CommonConstants.TWO_STRING;
					} else if (CommonConstants.ZERO_STRING.equals(t.getIsMustNow())) {
						isMustEditNew = CommonConstants.ZERO_STRING;
					} else {
						isMustEditNew = CommonConstants.ONE_STRING;
					}
					// 如果结果发生了变化，则更新：
					if (!t.getIsMustEdit().equals(isMustEditNew)) {
						tFascEditLog = new TFascEditLog();
						tFascEditLog.setMainId(t.getId());
						tFascEditLog.setMainType(CommonConstants.ONE_STRING);
						editContent = "“是否已配置”由“" + FascConstants.IS_MUST_EDIT_ARR[Integer.parseInt(t.getIsMustEdit())]
								+ "”→“" + FascConstants.IS_MUST_EDIT_ARR[Integer.parseInt(isMustEditNew)] + "”";
						tFascEditLog.setEditContent(editContent);
						logList.add(tFascEditLog);
						t.setIsMustEdit(isMustEditNew);
						updateList.add(t);
					}
				}
			}
			if (!updateList.isEmpty()) {
				for (TFascTemplate t : updateList) {
					tFascTemplateMapper.updateById(t);
				}
			}
			if (!logList.isEmpty()) {
				tFascEditLogService.saveBatch(logList);
			}
		}
		return R.ok();
	}
}
