package com.zksy.base.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zksy.base.domain.MaintenanceDataStat;
import com.zksy.base.mapper.MaintenanceDataStatMapper;
import com.zksy.base.service.MaintenanceDataStatService;
import com.zksy.common.exception.ServiceException;
import com.zksy.manhole.dto.in.MaintenanceDataStatQueryInDTO;
import com.zksy.manhole.dto.in.MaintenanceDataStatTrendInDTO;
import com.zksy.manhole.dto.out.AbnormalTerminalTrendOutDTO;
import com.zksy.manhole.dto.out.CaseRateTrendOutDTO;
import com.zksy.manhole.dto.out.MaintenanceDataStatOutDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.WeekFields;
import java.util.*;

/**
* @author Administrator
* @description 针对表【maintenance_data_stat(运维数据统计表)】的数据库操作Service实现
* @createDate 2026-06-26 14:11:51
*/
@Slf4j
@Service
public class MaintenanceDataStatServiceImpl extends ServiceImpl<MaintenanceDataStatMapper, MaintenanceDataStat>
    implements MaintenanceDataStatService{

    /**
     * 根据日期查询运维数据统计
     * @param queryInDTO
     * @return
     */
    @Override
    public MaintenanceDataStatOutDTO queryByDate(MaintenanceDataStatQueryInDTO queryInDTO) {
        log.info("根据日期查询运维数据统计-入参:{}", queryInDTO);
        LambdaQueryWrapper<MaintenanceDataStat> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(queryInDTO.getStatDate() != null, MaintenanceDataStat::getStatDate, queryInDTO.getStatDate())
                .eq(queryInDTO.getDeptId() != null, MaintenanceDataStat::getDeptId, queryInDTO.getDeptId());
        MaintenanceDataStat stat = this.getOne(queryWrapper);
        if(stat == null){
            return null;
        }
        return BeanUtil.copyProperties(stat, MaintenanceDataStatOutDTO.class);
    }

    /**
     * 周度/月度 异常终端设备数量趋势分析
     * @param inDTO
     * @return
     */
    @Override
    public List<AbnormalTerminalTrendOutDTO> abnormalTerminalTrend(MaintenanceDataStatTrendInDTO inDTO) {
        log.info("周度/月度 异常终端设备数量趋势分析-入参:{}", inDTO);
        List<MaintenanceDataStat> statList = queryStatList(inDTO);
        if(CollUtil.isEmpty(statList)){
            return new ArrayList<>();
        }
        // 按周度/月度分组
        Map<String, List<MaintenanceDataStat>> groupedMap = groupByPeriod(statList, inDTO.getTrendType());
        List<AbnormalTerminalTrendOutDTO> result = new ArrayList<>();
        for(Map.Entry<String, List<MaintenanceDataStat>> entry : groupedMap.entrySet()){
            List<MaintenanceDataStat> periodList = entry.getValue();
            AbnormalTerminalTrendOutDTO outDTO = new AbnormalTerminalTrendOutDTO();
            outDTO.setTrendLabel(entry.getKey());
            // 取该周期内第一条记录的统计日期作为代表日期
            outDTO.setStatDate(periodList.get(0).getStatDate());
            // 计算平均异常终端设备数量
            double avgAbnormal = periodList.stream()
                    .filter(s -> s.getAbnormalTerminal() != null)
                    .mapToInt(MaintenanceDataStat::getAbnormalTerminal)
                    .average()
                    .orElse(0);
            outDTO.setAbnormalTerminal((int) Math.round(avgAbnormal));
            result.add(outDTO);
        }
        // 按趋势标签排序
        result.sort(Comparator.comparing(AbnormalTerminalTrendOutDTO::getTrendLabel));
        return result;
    }

    /**
     * 周度/月度 案件处置率、案件延期率趋势分析
     * @param inDTO
     * @return
     */
    @Override
    public List<CaseRateTrendOutDTO> caseRateTrend(MaintenanceDataStatTrendInDTO inDTO) {
        log.info("周度/月度 案件处置率/延期率趋势分析-入参:{}", inDTO);
        List<MaintenanceDataStat> statList = queryStatList(inDTO);
        if(CollUtil.isEmpty(statList)){
            return new ArrayList<>();
        }
        // 按周度/月度分组
        Map<String, List<MaintenanceDataStat>> groupedMap = groupByPeriod(statList, inDTO.getTrendType());
        List<CaseRateTrendOutDTO> result = new ArrayList<>();
        for(Map.Entry<String, List<MaintenanceDataStat>> entry : groupedMap.entrySet()){
            List<MaintenanceDataStat> periodList = entry.getValue();
            CaseRateTrendOutDTO outDTO = new CaseRateTrendOutDTO();
            outDTO.setTrendLabel(entry.getKey());
            outDTO.setStatDate(periodList.get(0).getStatDate());
            // 计算平均案件处置率
            double avgDisposalRate = periodList.stream()
                    .filter(s -> s.getCaseDisposalRate() != null)
                    .mapToDouble(s -> s.getCaseDisposalRate().doubleValue())
                    .average()
                    .orElse(0);
            outDTO.setCaseDisposalRate(BigDecimal.valueOf(avgDisposalRate).setScale(2, RoundingMode.HALF_UP));
            // 计算平均案件延期率
            double avgDelayRate = periodList.stream()
                    .filter(s -> s.getCaseDelayRate() != null)
                    .mapToDouble(s -> s.getCaseDelayRate().doubleValue())
                    .average()
                    .orElse(0);
            outDTO.setCaseDelayRate(BigDecimal.valueOf(avgDelayRate).setScale(2, RoundingMode.HALF_UP));
            result.add(outDTO);
        }
        // 按趋势标签排序
        result.sort(Comparator.comparing(CaseRateTrendOutDTO::getTrendLabel));
        return result;
    }

    /**
     * 查询统计数据列表（公共方法）
     * @param inDTO
     * @return
     */
    private List<MaintenanceDataStat> queryStatList(MaintenanceDataStatTrendInDTO inDTO) {
        if(inDTO.getTrendType() == null){
            throw new ServiceException("趋势类型不能为空");
        }
        LambdaQueryWrapper<MaintenanceDataStat> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.ge(inDTO.getStartDate() != null, MaintenanceDataStat::getStatDate, inDTO.getStartDate())
                .le(inDTO.getEndDate() != null, MaintenanceDataStat::getStatDate, inDTO.getEndDate())
                .eq(inDTO.getDeptId() != null, MaintenanceDataStat::getDeptId, inDTO.getDeptId())
                .orderByAsc(MaintenanceDataStat::getStatDate);
        return this.list(queryWrapper);
    }

    /**
     * 按周度/月度分组
     * @param statList
     * @param trendType 1-周度 2-月度
     * @return
     */
    private Map<String, List<MaintenanceDataStat>> groupByPeriod(List<MaintenanceDataStat> statList, Integer trendType) {
        Map<String, List<MaintenanceDataStat>> groupedMap = new LinkedHashMap<>();
        WeekFields weekFields = WeekFields.of(Locale.getDefault());
        DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("yyyy-MM");
        for(MaintenanceDataStat stat : statList){
            LocalDate localDate = stat.getStatDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            String key;
            if(trendType == 1){
                // 周度：yyyy-Www
                int weekYear = localDate.get(weekFields.weekBasedYear());
                int weekNum = localDate.get(weekFields.weekOfWeekBasedYear());
                key = String.format("%d-W%02d", weekYear, weekNum);
            } else {
                // 月度：yyyy-MM
                key = localDate.format(monthFormatter);
            }
            groupedMap.computeIfAbsent(key, k -> new ArrayList<>()).add(stat);
        }
        return groupedMap;
    }
}




