package com.cmvr.vi.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cmvr.common.exception.GlobalException;
import com.cmvr.evaluation.model.domain.AeEvaluation;
import com.cmvr.evaluation.model.domain.AeIndicatorEntity;
import com.cmvr.evaluation.model.dto.AeIResultDTO;
import com.cmvr.evaluation.model.vo.AeViEvaluationVO;
import com.cmvr.evaluation.service.AeIndicatorService;
import com.cmvr.evaluation.service.IAeEvaluationService;
import com.cmvr.test.enums.FlowSceneTypeEnum;
import com.cmvr.test.enums.RunModeEnum;
import com.cmvr.test.flow.runtime.engine.FlowTaskRuntimeService;
import com.cmvr.test.model.domain.TeDetectionItem;
import com.cmvr.test.model.domain.TeTaskConfigInfo;
import com.cmvr.test.model.domain.TeTaskInst;
import com.cmvr.test.model.vo.TeQueryProjectOrchestraItemVO;
import com.cmvr.test.model.vo.TeTaskExecuteProjectVO;
import com.cmvr.test.service.ITeDetectionItemService;
import com.cmvr.test.service.ITeTaskConfigInfoService;
import com.cmvr.test.service.ITeTaskInstService;
import com.cmvr.vi.mapper.ViProjectMapper;
import com.cmvr.vi.model.domain.ViProject;
import com.cmvr.vi.model.domain.ViScheme;
import com.cmvr.vi.service.IViProjectService;
import com.cmvr.vi.service.IViSchemeService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 语音交互-项目Service业务层处理
 *
 * @author cmvr-iot
 */
@Service
@RequiredArgsConstructor
public class ViProjectServiceImpl extends ServiceImpl<ViProjectMapper, ViProject> implements IViProjectService {

    private final FlowTaskRuntimeService flowTaskRuntimeService;
    private final IViSchemeService viSchemeService;
    private final ITeDetectionItemService detectionItemService;
    private final ITeTaskConfigInfoService taskConfigInfoService;
    private final ITeTaskInstService taskInstService;
    private final IAeEvaluationService aeEvaluationService;
    private final AeIndicatorService aeIndicatorService;

    @Override
    public ViProject selectViProjectByProjectId(String projectId) {
        return this.getById(projectId);
    }

    @Override
    public List<ViProject> selectViProjectList(ViProject viProject) {
        LambdaQueryWrapper<ViProject> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ObjUtil.isNotEmpty(viProject.getProjectName()), ViProject::getProjectName, viProject.getProjectName())
                .eq(ObjUtil.isNotEmpty(viProject.getStatus()), ViProject::getStatus, viProject.getStatus());
        return this.list(wrapper);
    }

    @Override
    public int insertViProject(ViProject viProject) {
        viProject.setStatus("0");
        int insert = this.baseMapper.insert(viProject);
        TeTaskConfigInfo taskConfigInfo = new TeTaskConfigInfo();
        taskConfigInfo.setRunMode(RunModeEnum.VI_PROJECT.name());
        taskConfigInfo.setId(viProject.getProjectId());
        taskConfigInfo.setStatus("0");
        taskConfigInfo.setTaskName(StrUtil.format("{}_{}", RunModeEnum.VI_PROJECT, viProject.getProjectName()));
        taskConfigInfoService.save(taskConfigInfo);
        return insert;
    }

    @Override
    public int updateViProject(ViProject viProject) {
        return this.baseMapper.updateById(viProject);
    }

    @Override
    public int deleteViProjectByProjectIds(String[] projectIds) {
        taskConfigInfoService.deleteTeTaskConfigInfoByIds(projectIds);
        return this.baseMapper.deleteBatchIds(Arrays.asList(projectIds));
    }

    @Override
    public List<TeQueryProjectOrchestraItemVO> queryExecuteRunParams(String projectId) {
        // 方案信息
        List<ViScheme> viSchemes = viSchemeService.querySchemesByProjectId(projectId);

        List<TeQueryProjectOrchestraItemVO> result = new ArrayList<>();

        for (ViScheme scheme : viSchemes) {
            // 根据场景类型查找对应检测项流程
            String sceneTypeKey = FlowSceneTypeEnum.fromCode(scheme.getSceneType()).getSceneCode();
            TeDetectionItem item = detectionItemService.selectTeDetectionItemBySceneType(sceneTypeKey);
            if (item == null) {
                continue;
            }

            TeQueryProjectOrchestraItemVO vo = new TeQueryProjectOrchestraItemVO();
            vo.setSchemeId(scheme.getSchemeId());
            vo.setSchemeName(scheme.getSchemeName());
            vo.setItemId(item.getId());
            vo.setConfig(item.getConfig());
            vo.setItemName(item.getDetectName());
            vo.setOrderNum(scheme.getSort());

            result.add(vo);
        }

        // 重新归一化 1..N
        for (int i = 0; i < result.size(); i++) {
            result.get(i).setOrderNum(i + 1);
        }

        return result;
    }

    @Override
    public String executeProject(TeTaskExecuteProjectVO taskExecuteProjectVO) {
        TeTaskExecuteProjectVO normalVO = new TeTaskExecuteProjectVO();
        normalVO.setProjectId(taskExecuteProjectVO.getProjectId());
        normalVO.setRunParams(taskExecuteProjectVO.getRunParams());
        normalVO.setTerminalId(taskExecuteProjectVO.getTerminalId());
        String instId = flowTaskRuntimeService.executeProjectTask(normalVO);
        this.update(
                new LambdaUpdateWrapper<ViProject>()
                        .eq(ViProject::getProjectId, taskExecuteProjectVO.getProjectId())
                        .set(ViProject::getStatus, "1") //执行中
        );
        return instId;
    }

    @Override
    public String queryExecuteInstId(String projectId) {
        TeTaskInst latestTaskInst = getTeTaskInst(projectId);
        return latestTaskInst.getId();
    }

    @Override
    public TeTaskInst getTeTaskInst(String projectId) {
        LambdaQueryWrapper<ViProject> wrapperProject = Wrappers.lambdaQuery(ViProject.class);
        wrapperProject.eq(ViProject::getProjectId, projectId);
//                .eq(ViProject::getStatus, "0");
        ViProject project = this.getOne(wrapperProject);
        if (ObjUtil.isEmpty(project)) {
            throw new GlobalException("项目id为 [{}] 的任务不存在或未执行！", projectId);
        }
        LambdaQueryWrapper<TeTaskInst> wrapper = Wrappers.lambdaQuery(TeTaskInst.class);
        wrapper.eq(TeTaskInst::getTaskId, projectId)
                .orderByDesc(TeTaskInst::getCreateTime)
                .last("LIMIT 1");
        TeTaskInst latestTaskInst = taskInstService.getOne(wrapper);
        return latestTaskInst;
    }


    /*public List<AeViEvaluationVO> queryEvaluation(String projectId) {
        // 1. 查询项目
        ViProject project = getById(projectId);

        // 2. 查询实例ID
        String instId = queryExecuteInstId(projectId);

        // 3. 查询检测项（itemId -> schemeId）
        List<TeQueryProjectOrchestraItemVO> items = queryExecuteRunParams(projectId);

        Map<String, String> itemSchemeMap = items.stream()
                .filter(i -> StrUtil.isNotBlank(i.getItemId()) && StrUtil.isNotBlank(i.getSchemeId()))
                .collect(Collectors.toMap(
                        TeQueryProjectOrchestraItemVO::getItemId,
                        TeQueryProjectOrchestraItemVO::getSchemeId,
                        (a, b) -> a
                ));

        // 4. 查询评估数据
        List<AeEvaluation> evaluations = aeEvaluationService.queryEvaluation(instId);



        // 5. 获取指标定义
        List<AeIndicatorEntity> indicators = aeIndicatorService.getChildrenByParentIdWithLevelLimit(project.getIndicatorId(), 4, 0);

        // 6. 按 schemeId 分组评估数据
        Map<String, List<AeEvaluation>> schemaEvaluationMap = evaluations.stream()
                .map(e -> new AbstractMap.SimpleEntry<>(itemSchemeMap.get(e.getItemId()), e))
                .filter(entry -> StrUtil.isNotBlank(entry.getKey()))
                .collect(Collectors.groupingBy(
                        Map.Entry::getKey,
                        Collectors.mapping(Map.Entry::getValue, Collectors.toList())
                ));

        // 7. 计算每个 schemeId 的评估结果
        List<AeViEvaluationVO> resultList = new ArrayList<>();

        for (Map.Entry<String, List<AeEvaluation>> entry : schemaEvaluationMap.entrySet()) {
            String schemeId = entry.getKey();
            List<AeEvaluation> evalList = entry.getValue();

            List<AeViEvaluationVO.AeItemDetail> itemDetails = new ArrayList<>();

            long responseTimeSum = 0L;
            long responseTimeCount = 0L;
            long successCount = 0L;

            // 8. 计算每个评估项的响应时间得分和成功率得分
            for (AeEvaluation evaluation : evalList) {

                AeIResultDTO dto = JSON.parseObject(evaluation.getResult(), AeIResultDTO.class);

                // 创建评估项对象
                AeViEvaluationVO.AeItemDetail itemDto = new AeViEvaluationVO.AeItemDetail();
                itemDto.setAeId(evaluation.getAeId());
                itemDto.setContent(evaluation.getAvContent());
                itemDto.setItemResponseTime(dto.getResponseTime());
                // 判断是否成功
                boolean success = "成功".equals(dto.getOverallResult());


                if (success) {
                    itemDto.setSuccess(success);
                } else {
                    itemDto.setSuccess(false);
                    itemDto.setFailureReason(dto.getFailureReason());
                }

                itemDto.setVideoPath(dto.getVideoPath());
                itemDto.setExecutionDetail(dto.getExecutionDetail());
                // 汇总
                itemDetails.add(itemDto);

                // 汇总响应时间（计算平均响应时间）
                if (dto.getResponseTime() != null) {
                    responseTimeSum += dto.getResponseTime();
                    responseTimeCount++;
                }

                // 汇总成功项（用于计算成功率）
                if (success) {
                    successCount++;
                }
            }
            // 计算方案的平均响应时间及得分
            Long avgResponseTime = responseTimeCount == 0 ? 0L : responseTimeSum / responseTimeCount;
            Long responseTimeScore = calculateResponseTimeScore(avgResponseTime, indicators);

            // 计算方案的成功率及得分
            Long successRate = evalList.isEmpty() ? 0L : (successCount * 100) / evalList.size();
            Long successRateScore = calculateSuccessRateScore(successRate, indicators);

            // 创建 AeViEvaluationVO 并设置字段
            AeViEvaluationVO vo = new AeViEvaluationVO();
            vo.setSchemeId(schemeId);
            String schemeName = items.stream().filter(x -> x.getSchemeId().equals(schemeId)).findFirst().get().getSchemeName();
            vo.setSchemeName(schemeName);
            vo.setResponseTime(avgResponseTime);
            vo.setResponseTimeScore(responseTimeScore);
            vo.setSuccessRate(successRate);
            vo.setSuccessRateScore(successRateScore);
            vo.setItemDetails(itemDetails);

            resultList.add(vo);
        }

        return resultList;
    }*/
    @Override
    public List<AeViEvaluationVO> queryEvaluation(String projectId) {

        // 1. 查询项目
        ViProject project = getById(projectId);

        // 2. 查询实例ID
        String instId = queryExecuteInstId(projectId);

        // 3. 查询检测项（itemId -> schemeId）
        List<TeQueryProjectOrchestraItemVO> items = queryExecuteRunParams(projectId);

        Map<String, String> itemSchemeMap = items.stream()
                .filter(i -> StrUtil.isNotBlank(i.getItemId()) && StrUtil.isNotBlank(i.getSchemeId()))
                .collect(Collectors.toMap(
                        TeQueryProjectOrchestraItemVO::getItemId,
                        TeQueryProjectOrchestraItemVO::getSchemeId,
                        (a, b) -> a
                ));

        Map<String, String> schemeNameMap = items.stream()
                .filter(i -> StrUtil.isNotBlank(i.getSchemeId()))
                .collect(Collectors.toMap(
                        TeQueryProjectOrchestraItemVO::getSchemeId,
                        TeQueryProjectOrchestraItemVO::getSchemeName,
                        (a, b) -> a
                ));

        // 4. 查询评估数据（允许不完整）
        List<AeEvaluation> evaluations = aeEvaluationService.queryEvaluation(instId);

        if (CollUtil.isEmpty(evaluations)) {
            throw new GlobalException(StrUtil.format("暂无项目id为{}的数据", projectId));
        }

        // 5. 获取指标定义
        List<AeIndicatorEntity> indicators =
                aeIndicatorService.getChildrenByParentIdWithLevelLimit(
                        project.getIndicatorId(), 4, 0
                );

        // 6. 按 schemeId 分组评估数据
        Map<String, List<AeEvaluation>> schemaEvaluationMap = evaluations.stream()
                .map(e -> new AbstractMap.SimpleEntry<>(itemSchemeMap.get(e.getItemId()), e))
                .filter(entry -> StrUtil.isNotBlank(entry.getKey()))
                .collect(Collectors.groupingBy(
                        Map.Entry::getKey,
                        Collectors.mapping(Map.Entry::getValue, Collectors.toList())
                ));

        List<AeViEvaluationVO> resultList = new ArrayList<>();

        // 7. 按 scheme 处理
        for (Map.Entry<String, List<AeEvaluation>> entry : schemaEvaluationMap.entrySet()) {

            String schemeId = entry.getKey();
            List<AeEvaluation> evalList = entry.getValue();

            List<AeViEvaluationVO.AeItemDetail> itemDetails = new ArrayList<>();

            long responseTimeSum = 0L;
            long responseTimeCount = 0L;
            long successCount = 0L;

            // ===== 关键：scheme 是否全部完成 =====
            boolean allFinished = true;

            for (AeEvaluation evaluation : evalList) {

                AeViEvaluationVO.AeItemDetail itemDto = new AeViEvaluationVO.AeItemDetail();
                itemDto.setAeId(evaluation.getAeId());
                itemDto.setContent(evaluation.getAvContent());

                boolean finished =
                        StrUtil.isNotBlank(evaluation.getResult())
                                && evaluation.getStatus() != null
                                && evaluation.getStatus() != 0   // 待评估
                                && evaluation.getStatus() != 1;  // 评估中
                itemDto.setStatus(evaluation.getStatus());
                if (!finished) {
                    allFinished = false;

                    // 未完成，只返回基础信息

//                    itemDto.setExecutionDetail("评估尚未完成");
                    itemDetails.add(itemDto);
                    continue;
                }

                // ===== 已完成 =====
                AeIResultDTO dto = JSON.parseObject(evaluation.getResult(), AeIResultDTO.class);

                itemDto.setItemResponseTime(dto.getResponseTime());

                boolean success = "成功".equals(dto.getOverallResult());

                if (!success) {
                    itemDto.setFailureReason(dto.getFailureReason());
                }

                itemDto.setVideoPath(dto.getVideoPath());
                itemDto.setExecutionDetail(dto.getExecutionDetail());

                itemDetails.add(itemDto);

                // 汇总（即便先算，最终是否使用由 allFinished 决定）
                if (dto.getResponseTime() != null) {
                    responseTimeSum += dto.getResponseTime();
                    responseTimeCount++;
                }

                if (success) {
                    successCount++;
                }
            }

            // ===== 组装 VO =====
            AeViEvaluationVO vo = new AeViEvaluationVO();
            vo.setSchemeId(schemeId);
            vo.setSchemeName(schemeNameMap.getOrDefault(schemeId, ""));
            vo.setItemDetails(itemDetails);

            // ===== 核心规则：只要有一条未完成，就不算指标 =====
            if (!allFinished) {
                vo.setResponseTime(null);
                vo.setResponseTimeScore(null);
                vo.setSuccessRate(null);
                vo.setSuccessRateScore(null);
                resultList.add(vo);
                continue;
            }

            // ===== 全部完成，才计算指标 =====
            Long avgResponseTime =
                    responseTimeCount == 0 ? 0L : responseTimeSum / responseTimeCount;

            Long responseTimeScore =
                    calculateResponseTimeScore(avgResponseTime, indicators);

            Long successRate =
                    evalList.isEmpty() ? 0L : (successCount * 100) / evalList.size();

            Long successRateScore =
                    calculateSuccessRateScore(successRate, indicators);

            vo.setResponseTime(avgResponseTime);
            vo.setResponseTimeScore(responseTimeScore);
            vo.setSuccessRate(successRate);
            vo.setSuccessRateScore(successRateScore);

            resultList.add(vo);
        }

        return resultList;
    }

    // 计算响应时间得分
    private Long calculateResponseTimeScore(Long itemResponseTime, List<AeIndicatorEntity> indicators) {
        // 1. 查找"唤醒时间"指标
        AeIndicatorEntity responseTimeIndicator = findIndicatorByName(indicators, "唤醒时间");

        if (responseTimeIndicator == null) {
            return 0L; // 如果没有找到指标，返回 0 分
        }

        // 2. 获取响应时间指标的子指标（可能存在多个子指标，例如不同的响应时间区间）
        List<AeIndicatorEntity> children = responseTimeIndicator.getChildren();

        long score = 0L;

        // 3. 遍历子指标，根据响应时间计算得分
        for (AeIndicatorEntity child : children) {
            // 子指标的比较值（例如响应时间阈值）和符号（如 <, <=, >, >=）
            BigDecimal compareValue1 = child.getCompareNum1();
            BigDecimal compareValue2 = child.getCompareNum2();
            String symbol = child.getSymbol();

            // 4. 根据符号和阈值判断响应时间是否符合子指标的规则，计算得分
            if (compareResponseTime(itemResponseTime, compareValue1, compareValue2, symbol)) {
                score = child.getScore().longValue(); // 得分等于子指标的得分
                break; // 找到符合条件的子指标后直接返回得分
            }
        }

        return score;
    }

    // 计算成功率得分
    private Long calculateSuccessRateScore(Long successRate, List<AeIndicatorEntity> indicators) {
        // 查找成功率指标
        AeIndicatorEntity successRateIndicator = findIndicatorByName(indicators, "唤醒成功率");

        if (successRateIndicator == null) {
            return 0L; // 如果没有匹配的成功率指标，返回 0 分
        }
        List<AeIndicatorEntity> children = successRateIndicator.getChildren();

        long score = 0L;
        for (AeIndicatorEntity child : children) {
            // 子指标的比较值（例如响应时间阈值）和符号（如 <, <=, >, >=）
            BigDecimal compareValue1 = child.getCompareNum1();
            BigDecimal compareValue2 = child.getCompareNum2();
            String symbol = child.getSymbol();

            // 4. 根据符号和阈值判断响应时间是否符合子指标的规则，计算得分
            if (compareResponseTime(successRate, compareValue1, compareValue2, symbol)) {
                score = child.getScore().longValue(); // 得分等于子指标的得分
                break; // 找到符合条件的子指标后直接返回得分
            }
        }
        return score;
    }

    private boolean compareResponseTime(Long itemResponseTime, BigDecimal compareValue1, BigDecimal compareValue2, String symbol) {
        // 如果只有一个阈值，就执行单边判断
        if (compareValue2 == null) {
            return compareSingleSide(itemResponseTime, compareValue1, symbol);
        } else {
            // 如果有两个阈值，执行区间判断
            return compareRange(itemResponseTime, compareValue1, compareValue2, symbol);
        }
    }

    // 处理单边比较（例如：<=、>、<、>=）
    private boolean compareSingleSide(Long itemResponseTime, BigDecimal compareValue1, String symbol) {
        switch (symbol) {
            case "<=":
                return itemResponseTime <= compareValue1.longValue();
            case "<":
                return itemResponseTime < compareValue1.longValue();
            case ">":
                return itemResponseTime > compareValue1.longValue();
            case ">=":
                return itemResponseTime >= compareValue1.longValue();
            default:
                return false;
        }
    }

    // 处理区间比较（例如：<=，>=）
    private boolean compareRange(Long itemResponseTime, BigDecimal compareValue1, BigDecimal compareValue2, String symbol) {
        // 如果 compareValue1 > compareValue2，交换两者
        if (compareValue1.compareTo(compareValue2) > 0) {
            BigDecimal temp = compareValue1;
            compareValue1 = compareValue2;
            compareValue2 = temp;
        }

        switch (symbol) {
            case "≤":
                return itemResponseTime <= compareValue2.longValue() && itemResponseTime >= compareValue1.longValue();
            case "<":
                return itemResponseTime < compareValue2.longValue() && itemResponseTime >= compareValue1.longValue();
            case ">":
                return itemResponseTime > compareValue1.longValue() && itemResponseTime <= compareValue2.longValue();
            case "≥":
                return itemResponseTime >= compareValue1.longValue() && itemResponseTime <= compareValue2.longValue();
            default:
                return false;
        }
    }

    // 计算成功率得分
    private Long calculateSuccessRateScore(String overallResult, List<AeIndicatorEntity> indicators) {
        AeIndicatorEntity successRateIndicator = findIndicatorByName(indicators, "成功率");

        if (successRateIndicator == null) {
            return 0L; // 如果没有匹配的成功率指标
        }

        if ("成功".equals(overallResult)) {
            return successRateIndicator.getScore().longValue(); // 满分
        } else {
            return 0L; // 失败，得 0 分
        }
    }

    // 根据指标名称找到对应的指标
    private AeIndicatorEntity findIndicatorByName(List<AeIndicatorEntity> indicators, String indicatorName) {
        for (AeIndicatorEntity indicator : indicators) {
            if (indicator.getName().equals(indicatorName)) {
                return indicator;
            }
        }
        return null; // 如果找不到，返回null
    }


}
