package digital.laboratory.platform.entrustment.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import digital.laboratory.platform.common.core.exception.CheckedException;
import digital.laboratory.platform.common.core.util.R;
import digital.laboratory.platform.entrustment.entity.*;
import digital.laboratory.platform.entrustment.enums.AnalysisOptionEnums;
import digital.laboratory.platform.entrustment.enums.EntrustIdentificationSituationType;
import digital.laboratory.platform.entrustment.service.*;
import digital.laboratory.platform.entrustment.utils.ExcelUtils;
import digital.laboratory.platform.sys.entity.DrugLite;
import digital.laboratory.platform.sys.enums.entrust.EntrustBiologyType;
import digital.laboratory.platform.sys.feign.RemoteCommDrugService;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author ChenJiangBao
 * @version 1.0
 * @description: excel上传服务层接口 实现类
 * @date 2025/4/16 11:55
 */
@Service
public class ExcelUploadServiceImpl implements ExcelUploadService {

    @Resource
    private SampleService sampleService;

    @Resource
    private CaseEventService caseEventService;

    @Resource
    private EntrustmentService entrustmentService;

    @Resource
    private EntrustmentIdentificationMaterialService entrustmentIdentificationMaterialService;

    @Resource
    private RemoteCommDrugService remoteCommDrugService;

    @Resource
    private EntrustMaterialCheckoutResultService entrustMaterialCheckoutResultService;

    @Resource
    private SuspectService suspectService;

    /**
     * 上传两社人员名单Excel文件，并自动生成检材与检测结果数据
     *
     * @param file      Excel文件（包含人员信息）
     * @param entrustId 委托ID
     * @return 是否成功导入
     * @throws Exception 发生异常时抛出
     */
    @Override
    public Boolean uploadHairInspectExcel(MultipartFile file, String entrustId) throws Exception {

        // 1. 校验委托合法性
        Entrustment entrustment = entrustmentService.getById(entrustId);
        if (entrustment == null) {
            throw new CheckedException(String.format("委托id为 %s 的委托信息不存在！", entrustId));
        }
        if (!entrustment.getOldIdentificationResult().equals(EntrustIdentificationSituationType.TWO_AGENCY.getDesc())) {
            throw new CheckedException("当前不支持两社人员之外的委托信息进行导入！");
        }

        // 2. 获取案件与毒品信息
        // 2.1 校验案件信息
        CaseEvent cj = caseEventService.validateCaseInfo(entrustment.getCaseId());

        // 2.2 获取默认毒品（海洛因）


        // 2.3 获取所有毒品名称映射（便于匹配检测结果）
        R<List<DrugLite>> innerGetAllR = remoteCommDrugService.innerGetAll();
        List<DrugLite> drugLiteList = innerGetAllR.getData();
        Map<String, DrugLite> drugLiteMap = drugLiteList.stream()
                .collect(Collectors.toMap(DrugLite::getName, Function.identity()));

        // 3. 读取Excel内容（从第一行数据开始读取）
        int headIndex = 1;
        List<Map<String, String>> data = ExcelUtils.readExcel(file, headIndex);

        // 3.1 获取当前委托下已有检材数，作为orderNo起始编号
        int orderNo = entrustmentIdentificationMaterialService.lambdaQuery()
                .eq(EntrustmentIdentificationMaterial::getEntrustmentId, entrustId)
                .list().size() + 1;

        // 3.2 初始化结果对象集合
        List<EntrustMaterialCheckoutResult> results = new ArrayList<>();

        ArrayList<Suspect> suspects = new ArrayList<>();
        for (Map<String, String> datum : data) {
            Suspect suspect = new Suspect();
            suspect.setName(datum.get("姓名"));
            suspect.setIdNumber(datum.get("身份证号"));
            suspects.add(suspect);
        }
        if (CollUtil.isNotEmpty(suspects)){
            suspectService.remove(Wrappers.<Suspect>lambdaQuery()
                    .eq(Suspect::getEntrustId, entrustId));
            suspectService.addSuspectList(suspects, entrustId);
        }
        List<EntrustmentIdentificationMaterial> entrustmentIdentificationMaterialList = new ArrayList<>();

        // 4. 遍历Excel数据行，构建检材与检测结果
        for (Map<String, String> datum : data) {
            // 构建检材对象
            EntrustmentIdentificationMaterial material = new EntrustmentIdentificationMaterial();
            material.setEntrustmentId(entrustment.getId());
            material.setCaseId(entrustment.getCaseId());
            material.setName(datum.get("姓名") + "毛发");
            material.setRemark(datum.get("身份证号"));

            // 解析身份证号
            String idNum = datum.get("身份证号");
            if (idNum != null && idNum.length() == 18) {
                material.setBiologyGender(this.getSexByIdNum(idNum));
                material.setMaterialAge(Integer.valueOf(this.getAgeByIdNum(idNum)));
            }

            material.setDrawPlace(datum.get("采样单位"));
            material.setId(IdWorker.get32UUID().toUpperCase());

            // 检测结果解析
            ArrayList<DrugLite> matchedDrugs = new ArrayList<>();
            String[] drugs = datum.get("检测结果").split("、");
            if (drugs.length == 0 || (drugs.length == 1 && drugs[0].trim().isEmpty())){
                matchedDrugs.add(drugLiteMap.get("海洛因"));
            }else {
            boolean matched = false;
            for (String drugName : drugs) {
                if (drugLiteMap.containsKey(drugName)) {
                    matchedDrugs.add(drugLiteMap.get(drugName));
                    matched = true;
                }
            }
            if (!matched) {
                matchedDrugs.add(drugLiteMap.get("海洛因"));
            }
            }
            material.setCandidateDrugs(matchedDrugs);
//            if (!matchedDrugs.isEmpty()) {
//                EntrustMaterialCheckoutResult result = new EntrustMaterialCheckoutResult();
//                result.setId(material.getId());
//                result.setQualitativeResult(JSON.toJSONString(matchedDrugs));
//                result.setEntrustId(entrustId);
//                results.add(result);
//            }

            // 设置检材默认属性
            material.setBiologyType(EntrustBiologyType.HAIR.getDesc());
            material.setType("1");
            material.setTypeName("生物样本");
            material.setQuantity(new BigDecimal(50));
            material.setUnit("mg");
            material.setForm("黑色头发");
            material.setFormName("黑色头发");
            material.setOrderNo(orderNo);
            material.setImEntrustNumber(String.valueOf(orderNo));
            orderNo++;
            material.setPackComplete(true);
            material.setRtSampleQuantity(0);
            material.setDrawTime(LocalDateTime.now());
            material.setAnalysisOption(AnalysisOptionEnums.QUALITATIVE.getCode());

            entrustmentIdentificationMaterialService.setMaterialIdentificationNo(material, cj);
            material.setSample1No(sampleService.getNewSampleNo(material.getImNo(), 1));

            entrustmentIdentificationMaterialList.add(material);
        }
//        entrustMaterialCheckoutResultService.saveBatch(results);
        boolean isSave = entrustmentIdentificationMaterialService.saveBatch(entrustmentIdentificationMaterialList);
        String entrustReq = entrustmentService.buildEntrustReq(entrustmentIdentificationMaterialList);
        entrustment.setEntrustRequirement(entrustReq);
        entrustmentService.updateById(entrustment);
        // 5. 批量保存检材信息和检测结果
        return isSave;
    }


    public String getSexByIdNum(String idNumber) {
        // 去除空格并转换为大写
        idNumber = idNumber.trim().toUpperCase();

        // 校验身份证长度
        if (idNumber.length() == 18) {
            try {
                // 提取性别
                int genderCode = Integer.parseInt(idNumber.substring(16, 17));
                return genderCode % 2 == 0 ? "女" : "男";
            } catch (Exception e) {

            }
        }
        return "";
    }


    public String getAgeByIdNum(String idNumber) {
        if (idNumber.length() == 18) {
            try {
                // 提取出生日期并计算年龄
                String birthDateStr = idNumber.substring(6, 14);
                LocalDate birthDate = LocalDate.parse(birthDateStr, DateTimeFormatter.BASIC_ISO_DATE);
                LocalDate currentDate = LocalDate.now();
                long age = ChronoUnit.YEARS.between(birthDate, currentDate);
                return String.valueOf(age);

            } catch (Exception e) {
            }
        }
        return "";
    }
}
