package com.zt.plat.module.qms.business.bus.service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.collections4.map.HashedMap;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson2.JSON;

import com.zt.plat.framework.common.exception.ServiceException;
import com.zt.plat.framework.common.util.object.BeanUtils;
import com.zt.plat.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.zt.plat.framework.security.core.util.SecurityFrameworkUtils;
import com.zt.plat.module.qms.business.bus.controller.vo.BatchSampleAnalysisColumnRespVO;
import com.zt.plat.module.qms.business.bus.controller.vo.BusinessAssayParameterDataReqVO;
import com.zt.plat.module.qms.business.bus.controller.vo.BusinessAssayProjectAndParameterRespVO;
import com.zt.plat.module.qms.business.bus.controller.vo.BusinessAssayProjectDataReqVO;
import com.zt.plat.module.qms.business.bus.controller.vo.BusinessAssayTaskAnalysisSampleProjectRespVO;
import com.zt.plat.module.qms.business.bus.dal.dataobject.BusinessAssayParameterDataDO;
import com.zt.plat.module.qms.business.bus.dal.dataobject.BusinessAssayProjectDataDO;
import com.zt.plat.module.qms.business.bus.dal.dataobject.BusinessAssayTaskDO;
import com.zt.plat.module.qms.business.bus.dal.dataobject.BusinessAssayTaskDataDO;
import com.zt.plat.module.qms.business.bus.dal.dataobject.BusinessAssayTaskDetailDO;
import com.zt.plat.module.qms.business.bus.dal.mapper.BusinessAssayParameterDataMapper;
import com.zt.plat.module.qms.business.bus.dal.mapper.BusinessAssayProjectDataMapper;
import com.zt.plat.module.qms.business.bus.dal.mapper.BusinessAssayTaskDataMapper;
import com.zt.plat.module.qms.business.bus.dal.mapper.BusinessAssayTaskDetailMapper;
import com.zt.plat.module.qms.business.bus.dal.mapper.BusinessAssayTaskMapper;
import com.zt.plat.module.qms.business.config.controller.vo.ConfigAssayMethodProjectRangeRespVO;
import com.zt.plat.module.qms.business.config.dal.dataobject.ConfigAssayMethodDO;
import com.zt.plat.module.qms.business.config.dal.dataobject.ConfigAssayMethodProjectRangeDO;
import com.zt.plat.module.qms.business.config.dal.mapper.ConfigAssayMethodMapper;
import com.zt.plat.module.qms.business.config.dal.mapper.ConfigAssayMethodProjectRangeMapper;
import com.zt.plat.module.qms.common.data.dal.dataobject.DataCollectionDO;
import com.zt.plat.module.qms.common.data.service.DataCollectionService;
import com.zt.plat.module.qms.enums.QmsCommonConstant;

import jakarta.annotation.Resource;

/**
 * <b>SampleAnalysisServiceImpl</b>
 * <p>
 * 更新历史：
 * <pre> 版本         更新时间            更新者        更新内容<hr/>
 * V1.0      2025年9月22日          wxr         Add</pre>
 * <b>Copyright (C)  云南志者竟成科技有限公司</b> 
 * </p>
 * @author 王兴荣<wxr@wangxingrong.com>
 * @version V1.0 
 * @since 2025年9月22日
 */
@Service
public class SampleAnalysisServiceImpl implements SampleAnalysisService {
	
	@Resource
	private ConfigAssayMethodMapper configAssayMethodMapper;
	
	@Resource
	private ConfigAssayMethodProjectRangeMapper configAssayMethodProjectRangeMapper;
	
	@Resource
	private BusinessAssayTaskMapper businessAssayTaskMapper;
	
	@Resource
	private BusinessAssayTaskDetailMapper businessAssayTaskDetailMapper;
	
	@Resource
	private BusinessAssayTaskDataMapper businessAssayTaskDataMapper;
	
	@Resource
	private BusinessAssayProjectDataMapper businessAssayProjectDataMapper;
	
	@Resource
	private BusinessAssayParameterDataMapper businessAssayParameterDataMapper;
	
    @Resource
    private DataCollectionService dataCollectionService;

	@Override
	public BusinessAssayTaskAnalysisSampleProjectRespVO batchSampleAnalysisByTaskId(Long businessAssayTaskId) {
		BusinessAssayTaskAnalysisSampleProjectRespVO businessAssayTaskAnalysisSampleProjectRespVO = new BusinessAssayTaskAnalysisSampleProjectRespVO();
		BusinessAssayTaskDO businessAssayTaskDO = businessAssayTaskMapper.selectById(businessAssayTaskId);
		if (businessAssayTaskDO == null) {
			throw new ServiceException(500, "未找到任务分配单");
		}
		businessAssayTaskAnalysisSampleProjectRespVO.setBusinessAssayTaskId(businessAssayTaskId);
		businessAssayTaskAnalysisSampleProjectRespVO.setBusinessAssayTasNo(businessAssayTaskDO.getTaskNo());
		businessAssayTaskAnalysisSampleProjectRespVO.setBusinessAssayTasName(businessAssayTaskDO.getTaskName());
		businessAssayTaskAnalysisSampleProjectRespVO.setAssayOperator(businessAssayTaskDO.getAssayOperator());
		businessAssayTaskAnalysisSampleProjectRespVO.setAssayTime(businessAssayTaskDO.getAssayTime());
		businessAssayTaskAnalysisSampleProjectRespVO.setConfigAssayMethodId(businessAssayTaskDO.getConfigAssayMethodId());
		businessAssayTaskAnalysisSampleProjectRespVO.setDataCollectionId(businessAssayTaskDO.getFormDataCollectionId());
		businessAssayTaskAnalysisSampleProjectRespVO.setFormValue(businessAssayTaskDO.getFormValue());
		
		ConfigAssayMethodDO configAssayMethodDO = configAssayMethodMapper.selectById(businessAssayTaskDO.getConfigAssayMethodId());
		businessAssayTaskAnalysisSampleProjectRespVO.setConfigAssayMethodName(configAssayMethodDO.getName());
		businessAssayTaskAnalysisSampleProjectRespVO.setDataCollectionKey(configAssayMethodDO.getDataCollectionKey());

		//处理列
        List<BatchSampleAnalysisColumnRespVO> cloumns = new ArrayList<>();
        cloumns.add(new BatchSampleAnalysisColumnRespVO("sampleCode", "sampleCode", "样品编号", "200px", "200px", "string", null, null, null, null, false, null, null));
        cloumns.add(new BatchSampleAnalysisColumnRespVO("sampleName", "sampleName", "样品名称", "200px", "200px", "string", null, null, null, null, false, null, null));
        //cloumns.add(new BatchSampleAnalysisColumnRespVO("cupNumber", "cupNumber", "杯号", "200px", "200px", "string", null, null, null, null, true, null));
        
        
        List<BusinessAssayTaskDetailDO> businessAssayTaskDetailList = businessAssayTaskDetailMapper.selectList(new LambdaQueryWrapperX<BusinessAssayTaskDetailDO>().eq(BusinessAssayTaskDetailDO::getBusinessAssayTaskId, businessAssayTaskId));
        
        List<BusinessAssayTaskDataDO> businessAssayTaskDataList = businessAssayTaskDataMapper.selectList(new LambdaQueryWrapperX<BusinessAssayTaskDataDO>().eq(BusinessAssayTaskDataDO::getBusinessAssayTaskId, businessAssayTaskId).eq(BusinessAssayTaskDataDO::getConfigAssayMethodId, businessAssayTaskDO.getConfigAssayMethodId()));
        BusinessAssayTaskDataDO businessAssayTaskData = businessAssayTaskDataList.get(0);
        
        BusinessAssayProjectDataReqVO projectDataSearch = new BusinessAssayProjectDataReqVO();
        projectDataSearch.setBusinessAssayTaskDataId(businessAssayTaskData.getId());
        List<BusinessAssayProjectAndParameterRespVO> projectAndParameterList = businessAssayProjectDataMapper.selectProjectAndParameterBy(projectDataSearch);
        for (BusinessAssayProjectAndParameterRespVO ep : projectAndParameterList) {
        	String fieldIndex = "e" + ep.getDicId();
        	String title = ep.getShowName() + (StringUtils.isBlank(ep.getUnit()) ? "" : "(" + ep.getUnit() + ")");
        	boolean isEdit = StringUtils.isBlank(ep.getFormula());
        	cloumns.add(new BatchSampleAnalysisColumnRespVO(fieldIndex, fieldIndex + ".value", title,  "", "120px", ep.getDataType(), ep.getDecimalPosition(), null, ep.getFormula(), ep.getParamNo(), isEdit, ep.getUnit(), ep.getFillingWay()));
        	
        	if (StringUtils.isNotEmpty(ep.getFormula())) {
        		BusinessAssayParameterDataReqVO parameterDataSearch = new BusinessAssayParameterDataReqVO();
        		parameterDataSearch.setBusinessAssayProjectDataId(ep.getId());
                List<BusinessAssayProjectAndParameterRespVO> plist = businessAssayParameterDataMapper.selectProjectAndParameterBy(parameterDataSearch);
                for (BusinessAssayProjectAndParameterRespVO p : plist) {
                	fieldIndex = "p" + p.getDicId();
                	title = p.getShowName() + (StringUtils.isBlank(p.getUnit()) ? "" : "(" + p.getUnit() + ")");
                	isEdit = StringUtils.isBlank(p.getFormula());
                	cloumns.add(new BatchSampleAnalysisColumnRespVO(fieldIndex, fieldIndex + ".value", title,  "", "120px", p.getDataType(), p.getDecimalPosition(), null, p.getFormula(), p.getParamNo(), isEdit, p.getUnit(), p.getFillingWay()));
				}
			}
		}
        businessAssayTaskAnalysisSampleProjectRespVO.setColumns(cloumns);
        

        //处理数据
        List<Map<String, Object>> datas = new ArrayList<>();
        for (BusinessAssayTaskDataDO businessAssayTaskDataDO : businessAssayTaskDataList) {
        	BusinessAssayTaskDetailDO businessAssayTaskDetailDO = businessAssayTaskDetailList.stream().filter(f -> f.getSampleId().equals(businessAssayTaskDataDO.getBusinessSubSampleId())).findFirst().orElse(null);
        	
            Map<String, Object> map = new HashedMap<>();
            map.put("businessAssayTaskDataId", businessAssayTaskDataDO.getId());
            map.put("businessAssayTaskId", businessAssayTaskDataDO.getBusinessAssayTaskId());
            map.put("businessSubSampleId", businessAssayTaskDataDO.getBusinessSubSampleId());
            map.put("businessSubParentSampleId", businessAssayTaskDataDO.getBusinessSubParentSampleId());
            map.put("configAssayMethodId", businessAssayTaskDataDO.getConfigAssayMethodId());
            map.put("businessAssayTaskDetailId", businessAssayTaskDetailDO.getId());
            map.put("sampleCode", businessAssayTaskDetailDO.getSampleCode());
            map.put("sampleName", businessAssayTaskDetailDO.getSampleName());

            BusinessAssayProjectDataReqVO projectDataSearch2 = new BusinessAssayProjectDataReqVO();
            projectDataSearch2.setBusinessAssayTaskDataId(businessAssayTaskDataDO.getId());
            List<BusinessAssayProjectAndParameterRespVO> projectAndParameterList2 = businessAssayProjectDataMapper.selectProjectAndParameterBy(projectDataSearch2);
            for (BusinessAssayProjectAndParameterRespVO ep : projectAndParameterList2) {
				map.put("e" + ep.getDicId(), ep);
				if (StringUtils.isNotEmpty(ep.getFormula())) {
	        		BusinessAssayParameterDataReqVO parameterDataSearch = new BusinessAssayParameterDataReqVO();
	        		parameterDataSearch.setBusinessAssayProjectDataId(ep.getId());
	                List<BusinessAssayProjectAndParameterRespVO> plist = businessAssayParameterDataMapper.selectProjectAndParameterBy(parameterDataSearch);
	                for (BusinessAssayProjectAndParameterRespVO p : plist) {
	                	map.put("p" + p.getDicId(), p);
					}
				}
				
			}
            datas.add(map);
        }
        
        businessAssayTaskAnalysisSampleProjectRespVO.setDatas(datas);
        
        //查询区间范围
        List<ConfigAssayMethodProjectRangeDO> configAssayMethodProjectRangeDOList = configAssayMethodProjectRangeMapper.selectList(new LambdaQueryWrapperX<ConfigAssayMethodProjectRangeDO>().eq(ConfigAssayMethodProjectRangeDO::getConfigAssayMethodId, businessAssayTaskDO.getConfigAssayMethodId()));
        businessAssayTaskAnalysisSampleProjectRespVO.setConfigAssayMethodProjectRangeList(BeanUtils.toBean(configAssayMethodProjectRangeDOList, ConfigAssayMethodProjectRangeRespVO.class));
		
		return businessAssayTaskAnalysisSampleProjectRespVO;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveBatchSampleAnalysis(BusinessAssayTaskAnalysisSampleProjectRespVO vo) {
		BusinessAssayTaskDO businessAssayTaskDO = businessAssayTaskMapper.selectById(vo.getBusinessAssayTaskId());
		businessAssayTaskDO.setFormValue(vo.getFormValue());
		businessAssayTaskDO.setAssayTime(vo.getAssayTime());
		businessAssayTaskDO.setTaskAssayStatus(QmsCommonConstant.SAVED);
		//赋值数据集id
		if (vo.getDataCollectionId() == null) {
			ConfigAssayMethodDO configAssayMethodDO = configAssayMethodMapper.selectById(businessAssayTaskDO.getConfigAssayMethodId());
			DataCollectionDO dataCollectionDO = dataCollectionService.getLatestDataCollectionByKey(configAssayMethodDO.getDataCollectionKey());
			businessAssayTaskDO.setFormDataCollectionId(dataCollectionDO.getId());
		} else {
			businessAssayTaskDO.setFormDataCollectionId(vo.getDataCollectionId());
		}
		

//        List<BusinessAssayTaskDetailDO> businessAssayTaskDetailList = businessAssayTaskDetailMapper.selectList(new LambdaQueryWrapperX<BusinessAssayTaskDetailDO>().eq(BusinessAssayTaskDetailDO::getBusinessAssayTaskId, vo.getBusinessAssayTaskId()));
        
        List<BusinessAssayTaskDataDO> businessAssayTaskDataList = businessAssayTaskDataMapper.selectList(new LambdaQueryWrapperX<BusinessAssayTaskDataDO>().eq(BusinessAssayTaskDataDO::getBusinessAssayTaskId, vo.getBusinessAssayTaskId()).eq(BusinessAssayTaskDataDO::getConfigAssayMethodId, businessAssayTaskDO.getConfigAssayMethodId()));
        
        List<Long> businessAssayTaskDataIdList = businessAssayTaskDataList.stream().map(m -> m.getId()).collect(Collectors.toList());
        
        List<BusinessAssayProjectDataDO> businessAssayProjectDataList = businessAssayProjectDataMapper.selectList(new LambdaQueryWrapperX<BusinessAssayProjectDataDO>().in(BusinessAssayProjectDataDO::getBusinessAssayTaskDataId, businessAssayTaskDataIdList));
        List<Long> businessAssayProjectDataIdList = businessAssayProjectDataList.stream().map(m -> m.getId()).collect(Collectors.toList());
        
        List<BusinessAssayParameterDataDO> businessAssayParameterDataList = businessAssayParameterDataMapper.selectList(new LambdaQueryWrapperX<BusinessAssayParameterDataDO>().in(BusinessAssayParameterDataDO::getBusinessAssayProjectDataId, businessAssayProjectDataIdList));
        
		
		List<Map<String,Object>> datas = vo.getDatas();
		for (Map<String, Object> map : datas) {
//			Long businessAssayTaskDataId = (Long) map.get("businessAssayTaskDataId");
//          Long businessAssayTaskId = (Long) map.get("businessAssayTaskId");
//          Long businessSubSampleId = (Long) map.get("businessSubSampleId");
//          Long businessSubParentSampleId = (Long) map.get("businessSubParentSampleId");
//          Long configAssayMethodId = (Long) map.get("configAssayMethodId");
//          Long businessAssayTaskDetailId = (Long) map.get("businessAssayTaskDetailId");
//          String sampleCode = map.get("sampleCode");
//          String sampleName = map.get("sampleName");
            
            List<BusinessAssayProjectAndParameterRespVO> listBusinessAssayProjectAndParameter = new ArrayList<>();
            for (Map.Entry<String, Object> entry : map.entrySet()) {
//				String key = entry.getKey();
				Object val = entry.getValue();
				if (val instanceof String) {
					continue;
				}
				BusinessAssayProjectAndParameterRespVO businessAssayProjectAndParameter = JSON.parseObject(JSON.toJSONString(val), BusinessAssayProjectAndParameterRespVO.class);
				listBusinessAssayProjectAndParameter.add(businessAssayProjectAndParameter);
			}
            
            //BusinessAssayTaskDataDO businessAssayTaskDataDO = businessAssayTaskDataList.stream().filter(f -> f.getId().equals(businessAssayTaskDataId)).findFirst().orElse(null);
            
            
            for (BusinessAssayProjectAndParameterRespVO  pap : listBusinessAssayProjectAndParameter) {
				if ("project".equals(pap.getType())) {
					BusinessAssayProjectDataDO businessAssayProjectDataDO = businessAssayProjectDataList.stream().filter(f -> f.getId().equals(pap.getId())).findFirst().orElse(null);
					if (StringUtils.isNotBlank(pap.getValue())) {
						String dataType = pap.getDataType();//string-字符串，int-整数，decimal-小数,date-日期，datetime-时间
						switch (dataType) {
							case "int":
							case "date":
							case "datetime":
							case "string": 
								businessAssayProjectDataDO.setValue(pap.getValue());
								businessAssayProjectDataDO.setRemark(pap.getShowName() + ": " + pap.getValue());
								break;
							case "decimal":
								BigDecimal value = new BigDecimal(pap.getValue());
		                        value = value.setScale(pap.getDecimalPosition(), RoundingMode.HALF_EVEN);
								businessAssayProjectDataDO.setValue(value.toPlainString());
								businessAssayProjectDataDO.setRemark(pap.getShowName() + ": " + value.toPlainString());	
								break;
							default:
								throw new IllegalArgumentException("Unexpected value: " + dataType);
						}
						
						
					} else {
						businessAssayProjectDataDO.setValue(null);
					}
					
					
				} else if ("parameter".equals(pap.getType())) {
					BusinessAssayParameterDataDO businessAssayParameterDataDO = businessAssayParameterDataList.stream().filter(f -> f.getId().equals(pap.getId())).findFirst().orElse(null);
					if (StringUtils.isNotBlank(pap.getValue())) {
						String dataType = pap.getDataType();//string-字符串，int-整数，decimal-小数,date-日期，datetime-时间
						switch (dataType) {
							case "int":
							case "date":
							case "datetime":
							case "string": 
								businessAssayParameterDataDO.setValue(pap.getValue());
								businessAssayParameterDataDO.setRemark(pap.getShowName() + ": " + pap.getValue());
								break;
							case "decimal":
								BigDecimal value = new BigDecimal(pap.getValue());
		                        value = value.setScale(pap.getDecimalPosition(), RoundingMode.HALF_EVEN);
		                        businessAssayParameterDataDO.setValue(value.toPlainString());
		                        businessAssayParameterDataDO.setRemark(pap.getShowName() + ": " + value.toPlainString());	
								break;
							default:
								throw new IllegalArgumentException("Unexpected value: " + dataType);
						}
					} else {
						businessAssayParameterDataDO.setValue(null);
					}
				}
			}
            
		}
		
		
		
		businessAssayTaskMapper.updateById(businessAssayTaskDO);
		businessAssayProjectDataMapper.updateBatch(businessAssayProjectDataList);
		businessAssayParameterDataMapper.updateBatch(businessAssayParameterDataList);
	}

	@Override
	public void submitSampleAnalysisByTaskId(Long businessAssayTaskId) {
		String loginUserNickname = SecurityFrameworkUtils.getLoginUserNickname();
		BusinessAssayTaskDO businessAssayTaskDO = businessAssayTaskMapper.selectById(businessAssayTaskId);
		businessAssayTaskDO.setTaskAssayStatus(QmsCommonConstant.SUBMITTED);
		businessAssayTaskDO.setAssaySubmitTime(LocalDateTime.now());
		businessAssayTaskDO.setFinishStatus(QmsCommonConstant.NOT_START);
		businessAssayTaskDO.setFlowStatus(QmsCommonConstant.NOT_START);
		businessAssayTaskMapper.updateById(businessAssayTaskDO);
	}

}
