package com.sundot.airport.ledger.service.impl;

import com.sundot.airport.common.core.domain.entity.SysDept;
import com.sundot.airport.common.core.domain.entity.SysUser;
import com.sundot.airport.common.enums.DeptTypeEnum;
import com.sundot.airport.common.enums.ScoreLevelEnum;
import com.sundot.airport.common.utils.StringUtils;
import com.sundot.airport.ledger.domain.ScoreDimension;
import com.sundot.airport.ledger.domain.ScoreEvent;
import com.sundot.airport.ledger.domain.vo.EmployeePortraitVO;
import com.sundot.airport.ledger.dto.DeptPortraitQueryDTO;
import com.sundot.airport.ledger.dto.GroupPortraitDTO;
import com.sundot.airport.ledger.mapper.ScoreDimensionMapper;
import com.sundot.airport.ledger.mapper.ScoreEventMapper;
import com.sundot.airport.ledger.service.IGroupPortraitService;
import com.sundot.airport.system.mapper.SysDeptMapper;
import com.sundot.airport.system.mapper.SysUserMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <b>功能名：</b>GroupPortraitServiceImpl<br>
 * <b>说明：</b> 组织画像Service实现（小组/通道维度）<br>
 * <b>著作权：</b> Copyright (C) 2025 SUNDOT CORPORATION<br>
 *
 * @author Claude
 */
@Service
public class GroupPortraitServiceImpl implements IGroupPortraitService {

    private static final Logger log = LoggerFactory.getLogger(GroupPortraitServiceImpl.class);

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Autowired
    private ScoreEventMapper scoreEventMapper;

    @Autowired
    private ScoreDimensionMapper scoreDimensionMapper;

    @Override
    public GroupPortraitDTO getGroupPortrait(DeptPortraitQueryDTO query) {
        // 1. 获取部门信息
        SysDept dept = sysDeptMapper.selectDeptById(query.getDeptId());
        if (dept == null) {
            throw new RuntimeException("部门不存在");
        }

        // 2. 查询部门所有成员
        SysUser userQuery = new SysUser();
        userQuery.setDeptId(query.getDeptId());
        userQuery.setStatus("0");
        List<SysUser> members = sysUserMapper.selectUserList(userQuery);

        if (members == null || members.isEmpty()) {
            throw new RuntimeException("该部门暂无成员");
        }

        // 3. 构建组织画像DTO
        GroupPortraitDTO portrait = new GroupPortraitDTO();
        portrait.setDeptId(dept.getDeptId());
        portrait.setDeptName(dept.getDeptName());
        portrait.setDeptType(dept.getDeptType());
        portrait.setPeriod(query.getStartDate() + " ~ " + query.getEndDate());
        portrait.setMemberCount(members.size());

        // 4. 计算各维度得分
        List<GroupPortraitDTO.DimensionScore> dimensions = calculateDimensions( dept, query);
        portrait.setDimensions(dimensions);

        // 5. 计算综合评分（加权平均）
        BigDecimal totalScore = calculateTotalScore(dimensions);
        portrait.setTotalScore(totalScore);

        return portrait;
    }

    /**
     * 计算各维度得分
     * 核心逻辑：
     * 1. 根据当前部门层级查询对应维度
     * 2. 通过dimRelationship找到下级维度
     * 3. 如果下级有值，用下级平均值；否则用基础分
     * 4. 加上当前层级特有分值
     */
    private List<GroupPortraitDTO.DimensionScore> calculateDimensions( SysDept dept, DeptPortraitQueryDTO query) {
        // 1. 根据部门类型确定org值
        String org = determineOrgByDeptType(dept.getDeptType());
        if(StringUtils.isEmpty( org)){
            return new ArrayList<>();
        }

        // 2. 查询当前层级的所有维度定义
        ScoreDimension dq = new ScoreDimension();
        dq.setOrg(org);
        dq.setStatus("0");
        List<ScoreDimension> dims = scoreDimensionMapper.selectList(dq);
        dims.sort(Comparator.comparing(d -> d.getSortOrder() == null ? 999 : d.getSortOrder()));

        List<GroupPortraitDTO.DimensionScore> result = new ArrayList<>();
        String beginTime = query.getStartDate()+" 00:00:00";
        String endTime = query.getEndDate()+" 23:59:59";
        for (ScoreDimension dim : dims) {
            // 3. 通过dimRelationship找到下级维度，计算下级平均值
            BigDecimal lowerLevelAverage = calculateLowerLevelAverage(dim,beginTime , endTime,dept.getDeptId());
            
            // 4. 获取基础分（如果下级有值就不用基础分）
            BigDecimal baseScore = dim.getBaseScore() != null ? dim.getBaseScore() : BigDecimal.ZERO;
            
            // 5. 决定使用下级平均值还是基础分
            BigDecimal averageScore = lowerLevelAverage.compareTo(BigDecimal.ZERO) > 0 
                    ? lowerLevelAverage 
                    : baseScore;

            // 6. 计算当前层级特有加减分
            Map<String, Object> specialScores = calculateSpecialScores(dim.getId(), query.getDeptId(),
                    beginTime, endTime,org);
            BigDecimal addScore = (BigDecimal) specialScores.getOrDefault("add", BigDecimal.ZERO);
            BigDecimal subtractScore = (BigDecimal) specialScores.getOrDefault("subtract", BigDecimal.ZERO);
            BigDecimal specialTotal = addScore.subtract(subtractScore);
            
            // 获取特有条目明细
            @SuppressWarnings("unchecked")
            List<GroupPortraitDTO.SpecialDetail> specialDetails = 
                    (List<GroupPortraitDTO.SpecialDetail>) specialScores.getOrDefault("details", new ArrayList<>());

            // 7. 最终分值 = 下级平均值(或基础分) + 特有合计
            BigDecimal finalScore = averageScore.add(specialTotal);

            // 8. 计算贡献分值
            BigDecimal weight = dim.getWeight() != null ? dim.getWeight() : BigDecimal.ZERO;
            BigDecimal contribution = finalScore.multiply(weight)
                    .divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);

            // 9. 组装维度得分项
            GroupPortraitDTO.DimensionScore item = new GroupPortraitDTO.DimensionScore();
            item.setName(dim.getName());
            item.setGroupAverageScore(lowerLevelAverage.setScale(2, RoundingMode.HALF_UP));
            item.setBaseScore(baseScore.setScale(2, RoundingMode.HALF_UP));
            item.setAddScore(addScore.setScale(2, RoundingMode.HALF_UP));
            item.setSubtractScore(subtractScore.setScale(2, RoundingMode.HALF_UP));
            item.setSpecialTotal(specialTotal.setScale(2, RoundingMode.HALF_UP));
            item.setFinalScore(finalScore.setScale(2, RoundingMode.HALF_UP));
            item.setWeight(weight);
            item.setContribution(contribution);
            item.setSpecialDetails(specialDetails);

            result.add(item);
        }

        return result;
    }

    /**
     * 根据部门类型确定org值
     * 使用DeptTypeEnum和ScoreLevelEnum枚举
     * 
     * 部门类型 → 配分层级映射：
     * - BRIGADE(部门) → DEPT(部门维度)
     * - MANAGER(班组) → TEAM(队室维度)
     * - TEAMS(小组) → GROUP(小组维度)
     */
    private String determineOrgByDeptType(String deptType) {
        if (deptType == null || deptType.isEmpty()) {
            return null;
        }
        
        // TEAMS(小组) → GROUP(小组维度)
        if (DeptTypeEnum.TEAMS.getCode().equals(deptType)) {
            return ScoreLevelEnum.GROUP.getCode();
        }
        
        // MANAGER(班组) → TEAM(队室维度)
        if (DeptTypeEnum.MANAGER.getCode().equals(deptType)) {
            return ScoreLevelEnum.TEAM.getCode();
        }
        
        // BRIGADE(部门)→ DEPT(部门维度)
        if (DeptTypeEnum.BRIGADE.getCode().equals(deptType)) {
            return ScoreLevelEnum.DEPT.getCode();
        }
        
        return null;
    }

    /**
     * 计算下级维度平均值
     * 层级关系：部门(DEPT) → 队/班组(TEAM) → 小组(GROUP) → 人员(PERSON)
     * 递进逻辑：
     * - org=DEPT → 获取子班组列表 → 计算每个班组的最终分数 → 求平均值
     * - org=TEAM → 获取子小组列表 → 计算每个小组的最终分数 → 求平均值
     * - org=GROUP → 查询org=PERSON的维度 → 计算人员事件平均
     * - org=PERSON → 最底层，直接返回0
     */
    private BigDecimal calculateLowerLevelAverage(ScoreDimension currentDim, String beginTime, String endTime, Long deptId) {
        String dimRelationship = currentDim.getDimRelationship();
        String currentOrg = currentDim.getOrg();
        
        // 1. 如果没有对照关系或已是最底层(org=PERSON)，返回0
        if (dimRelationship == null || dimRelationship.isEmpty() || ScoreLevelEnum.PERSON.getCode().equals(currentOrg)) {
            return BigDecimal.ZERO;
        }
        
        // 2. 查找下一层级的org值
        String lowerOrg = getLowerLevelOrg(currentOrg);
        if (lowerOrg == null) {
            return BigDecimal.ZERO;
        }

        // 3. 查询下一级维度（通过dimRelationship匹配）
        ScoreDimension query = new ScoreDimension();
        query.setDimRelationship(dimRelationship);
        query.setOrg(lowerOrg);
        query.setStatus("0");
        List<ScoreDimension> lowerDims = scoreDimensionMapper.selectList(query);
        
        if (lowerDims == null || lowerDims.isEmpty()) {
            log.warn("未找到下级维度，对照关系: {}, 目标org: {}", dimRelationship, lowerOrg);
            return BigDecimal.ZERO;
        }
        
        // 取第一个匹配的维度
        ScoreDimension lowerDim = lowerDims.get(0);

        // 4. 根据下一级的org决定如何处理
        if (ScoreLevelEnum.PERSON.getCode().equals(lowerOrg)) {
            // 下一级是人员维度，计算人员事件平均值
            return calculatePersonDimensionAverage(lowerDim, beginTime, endTime, deptId);
        } else {
            // 下一级是 TEAM 或 GROUP 层级，需要获取子部门并计算每个子部门的最终分数
            return calculateChildDeptAverage(lowerDim, beginTime, endTime, deptId);
        }
    }

    /**
     * 计算子部门的平均分数
     * 对于 TEAM 和 GROUP 层级，需要获取子部门列表，计算每个子部门的最终分数，然后求平均
     */
    private BigDecimal calculateChildDeptAverage(ScoreDimension lowerDim, String beginTime, String endTime, Long deptId) {
        // 获取子部门列表
        List<SysDept> childDepts = sysDeptMapper.selectChildrenDeptById(deptId);
        
        if (childDepts == null || childDepts.isEmpty()) {
            log.info("部门 {} 没有子部门", deptId);
            return BigDecimal.ZERO;
        }

        BigDecimal totalScore = BigDecimal.ZERO;
        int count = 0;

        for (SysDept childDept : childDepts) {
            // 计算该子部门在当前维度下的最终分数
            BigDecimal childScore = calculateChildDeptDimensionScore(lowerDim, beginTime, endTime, childDept.getDeptId());
            if (childScore.compareTo(BigDecimal.ZERO) > 0) {
                totalScore = totalScore.add(childScore);
                count++;
            }
        }

        if (count == 0) {
            return BigDecimal.ZERO;
        }

        return totalScore.divide(BigDecimal.valueOf(count), 2, RoundingMode.HALF_UP);
    }

    /**
     * 计算单个子部门在指定维度下的最终分数
     * 最终分数 = 下级平均值(或基础分) + 特有加减分
     */
    private BigDecimal calculateChildDeptDimensionScore(ScoreDimension dim, String beginTime, String endTime, Long deptId) {
        String currentOrg = dim.getOrg();
        
        // 1. 递归计算下级平均值
        BigDecimal lowerLevelAverage = calculateLowerLevelAverage(dim, beginTime, endTime, deptId);
        
        // 2. 获取基础分（如果下级有值就不用基础分）
        BigDecimal baseScore = dim.getBaseScore() != null ? dim.getBaseScore() : BigDecimal.ZERO;
        
        // 3. 决定使用下级平均值还是基础分
        BigDecimal averageScore = lowerLevelAverage.compareTo(BigDecimal.ZERO) > 0 
                ? lowerLevelAverage 
                : baseScore;

        // 4. 计算当前层级特有加减分
        Map<String, Object> specialScores = calculateSpecialScores(dim.getId(), deptId, beginTime, endTime, currentOrg);
        BigDecimal addScore = (BigDecimal) specialScores.getOrDefault("add", BigDecimal.ZERO);
        BigDecimal subtractScore = (BigDecimal) specialScores.getOrDefault("subtract", BigDecimal.ZERO);
        BigDecimal specialTotal = addScore.subtract(subtractScore);

        // 5. 最终分值 = 下级平均值(或基础分) + 特有合计
        return averageScore.add(specialTotal);
    }

    /**
     * 计算人员维度平均值
     * 最底层（org=4），查询该维度下的所有人员事件，计算平均分数
     */
    private BigDecimal calculatePersonDimensionAverage(ScoreDimension dimension, String beginTime, String endTime,Long deptId) {

        // 查询该维度下的所有事件
        ScoreEvent eventQuery = new ScoreEvent();
        eventQuery.setDimensionId(dimension.getId());
        if (beginTime != null && !beginTime.isEmpty()) {
            eventQuery.getParams().put("beginTime", beginTime);
        }
        if (endTime != null && !endTime.isEmpty()) {
            eventQuery.getParams().put("endTime", endTime);
        }
        eventQuery.setGroupId(deptId);
        List<ScoreEvent> events = scoreEventMapper.selectList(eventQuery);

        BigDecimal base = dimension.getBaseScore() != null ? dimension.getBaseScore() : BigDecimal.valueOf(80);
        if (events == null || events.isEmpty()) {
            log.info("人员维度无事件数据");
            return base;
        }

        // 按人员分组统计总分
        Map<String, BigDecimal> personScores = new HashMap<>();
        for (ScoreEvent e : events) {
            String personName = e.getPersonName();
            if (personName == null || personName.trim().isEmpty()) continue;

            // 支持逗号分隔多人
            String[] names = personName.split("[,，]");
            for (String name : names) {
                String trimmedName = name.trim();
                if (trimmedName.isEmpty()) continue;

                BigDecimal score = e.getTotalScore() != null ? e.getTotalScore() : BigDecimal.ZERO;
                personScores.merge(trimmedName, score, BigDecimal::add);
            }
        }

        if (personScores.isEmpty()) {
            return BigDecimal.ZERO;
        }
        BigDecimal bigDecimal = BigDecimal.valueOf(personScores.size());
        BigDecimal sum = personScores.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);


        BigDecimal dimScore = base.multiply(bigDecimal).add(sum);
        return dimScore.divide(bigDecimal, 2, RoundingMode.HALF_UP);
    }

    /**
     * 获取下级层级的org值
     * 使用ScoreLevelEnum枚举
     * 层级关系：部门(DEPT) -> 队(TEAM) -> 小组(GROUP) -> 员工(PERSON)
     */
    private String getLowerLevelOrg(String currentOrg) {
        if (currentOrg == null) {
            return null;
        }
        if (ScoreLevelEnum.DEPT.getCode().equals(currentOrg)) {
            return ScoreLevelEnum.TEAM.getCode();
        } else if (ScoreLevelEnum.TEAM.getCode().equals(currentOrg)) {
            return ScoreLevelEnum.GROUP.getCode();
        } else if (ScoreLevelEnum.GROUP.getCode().equals(currentOrg)) {
            return ScoreLevelEnum.PERSON.getCode();
        }
        return null;
    }

    /**
     * 计算小组特有加减分及明细
     * 注：特有事件通过当前org层级筛选
     */
    private Map<String, Object> calculateSpecialScores(Long dimensionId, Long deptId, String beginTime, String endTime, String org) {
        Map<String, Object> result = new HashMap<>();
        result.put("add", BigDecimal.ZERO);
        result.put("subtract", BigDecimal.ZERO);
        result.put("details", new ArrayList<GroupPortraitDTO.SpecialDetail>());

        // 查询该部门在该维度的特有事件（根据org参数筛选）
        ScoreEvent eventQuery = new ScoreEvent();
        eventQuery.setDimensionId(dimensionId);
        if(ScoreLevelEnum.GROUP.getCode().equals(org)){
            eventQuery.setGroupId(deptId);
        }else if(ScoreLevelEnum.TEAM.getCode().equals(org)){
            eventQuery.setTeamId(deptId);
        }else if(ScoreLevelEnum.DEPT.getCode().equals(org)){
            eventQuery.setDeptId(deptId);
        }
        eventQuery.setOrg(org); // 使用传入的org参数
        if (beginTime != null && !beginTime.isEmpty()) {
            eventQuery.getParams().put("beginTime", beginTime);
        }
        if (endTime != null && !endTime.isEmpty()) {
            eventQuery.getParams().put("endTime", endTime);
        }
        List<ScoreEvent> events = scoreEventMapper.selectList(eventQuery);

        List<GroupPortraitDTO.SpecialDetail> details = new ArrayList<>();
        
        if (events == null || events.isEmpty()) {
            return result;
        }

        // 分别累计加分和减分
        BigDecimal addTotal = BigDecimal.ZERO;
        BigDecimal subtractTotal = BigDecimal.ZERO;
        
        // 使用Map按指标汇总：key为"二级_三级_四级"，value为明细对象
        Map<String, GroupPortraitDTO.SpecialDetail> summaryMap = new LinkedHashMap<>();

        for (ScoreEvent e : events) {
            BigDecimal score = e.getTotalScore() != null ? e.getTotalScore() : BigDecimal.ZERO;
            
            // 构建汇总key：二级+三级+四级指标名称
            String summaryKey = buildSummaryKey(e.getLevel2Name(), e.getLevel3Name(), e.getLevel4Name());
            
            // 如果该指标已存在，则累加分值
            if (summaryMap.containsKey(summaryKey)) {
                GroupPortraitDTO.SpecialDetail existingDetail = summaryMap.get(summaryKey);
                BigDecimal newScore = existingDetail.getScore().add(score);
                existingDetail.setScore(newScore);
                // 更新类型（如果分值变号）
                existingDetail.setType(newScore.compareTo(BigDecimal.ZERO) >= 0 ? "加分" : "减分");
            } else {
                // 组装明细项
                GroupPortraitDTO.SpecialDetail detail = new GroupPortraitDTO.SpecialDetail();
                detail.setLevel2Name(e.getLevel2Name());
                detail.setLevel3Name(e.getLevel3Name());
                detail.setLevel4Name(e.getLevel4Name());
                detail.setScore(score);
                detail.setEventDesc(e.getEventDesc());
                detail.setType(score.compareTo(BigDecimal.ZERO) >= 0 ? "加分" : "减分");
                summaryMap.put(summaryKey, detail);
            }
            
            if (score.compareTo(BigDecimal.ZERO) > 0) {
                addTotal = addTotal.add(score);
            } else {
                subtractTotal = subtractTotal.add(score.abs());
            }
        }
        
        // 将汇总后的明细转换为List
        details.addAll(summaryMap.values());

        result.put("add", addTotal);
        result.put("subtract", subtractTotal);
        result.put("details", details);

        return result;
    }

    /**
     * 构建汇总key：二级+三级+四级指标名称
     */
    private String buildSummaryKey(String level2Name, String level3Name, String level4Name) {
        return (level2Name != null ? level2Name : "") + "_" +
               (level3Name != null ? level3Name : "") + "_" +
               (level4Name != null ? level4Name : "");
    }

    /**
     * 计算综合评分（各维度贡献分值之和）
     */
    private BigDecimal calculateTotalScore(List<GroupPortraitDTO.DimensionScore> dimensions) {
        BigDecimal total = dimensions.stream()
                .map(GroupPortraitDTO.DimensionScore::getContribution)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        return total.setScale(2, RoundingMode.HALF_UP);
    }
}