package com.rj.service.biz.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rj.entity.CpaBrandScoreStatistics;
import com.rj.mapper.CpaBrandScoreStatisticsMapper;
import com.rj.service.biz.ICpaBrandScoreStatisticsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 经销商品牌得分统计表 服务实现类
 * 
 * @author 李中华
 * @date 2025/1/15
 */
@Slf4j
@Service
public class CpaBrandScoreStatisticsServiceImpl extends ServiceImpl<CpaBrandScoreStatisticsMapper, CpaBrandScoreStatistics> 
        implements ICpaBrandScoreStatisticsService {

    @Autowired
    private CpaBrandScoreStatisticsMapper cpaBrandScoreStatisticsMapper;

    @Override
    public List<CpaBrandScoreStatistics> getByDealerCodeAndType(String dealerCode, String statisticsType) {
        return cpaBrandScoreStatisticsMapper.selectByDealerCodeAndType(dealerCode, statisticsType);
    }

    @Override
    public List<CpaBrandScoreStatistics> getByBigAreaAndType(String bigArea, String statisticsType) {
        return cpaBrandScoreStatisticsMapper.selectByBigAreaAndType(bigArea, statisticsType);
    }

    @Override
    public List<CpaBrandScoreStatistics> getByDateRange(LocalDate startDate, LocalDate endDate, String statisticsType) {
        return cpaBrandScoreStatisticsMapper.selectByDateRange(startDate, endDate, statisticsType);
    }

    @Override
    public List<Map<String, Object>> getDealerRanking(String statisticsType, Integer limit) {
        return cpaBrandScoreStatisticsMapper.selectDealerRanking(statisticsType, limit);
    }

    @Override
    public List<Map<String, Object>> getBigAreaRanking(String statisticsType) {
        return cpaBrandScoreStatisticsMapper.selectBigAreaRanking(statisticsType);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchSave(List<CpaBrandScoreStatistics> statisticsList) {
        try {
            if (statisticsList == null || statisticsList.isEmpty()) {
                log.warn("批量保存统计数据为空");
                return false;
            }
            
            // 设置创建时间
            LocalDateTime now = LocalDateTime.now();
            statisticsList.forEach(statistics -> {
                if (statistics.getCreatedAt() == null) {
                    statistics.setCreatedAt(now);
                }
                if (statistics.getUpdatedAt() == null) {
                    statistics.setUpdatedAt(now);
                }
                if (statistics.getIsDeleted() == null) {
                    statistics.setIsDeleted(0);
                }
            });
            
            int result = cpaBrandScoreStatisticsMapper.batchInsert(statisticsList);
            log.info("批量保存统计数据成功，保存记录数：{}", result);
            return result > 0;
        } catch (Exception e) {
            log.error("批量保存统计数据失败", e);
            throw e;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteByCondition(String dealerCode, String statisticsType, LocalDate startDate, LocalDate endDate) {
        try {
            int result = cpaBrandScoreStatisticsMapper.deleteByCondition(dealerCode, statisticsType, startDate, endDate);
            log.info("根据条件删除统计数据成功，删除记录数：{}", result);
            return result >= 0;
        } catch (Exception e) {
            log.error("根据条件删除统计数据失败", e);
            throw e;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int generateAndSaveStatistics(String statisticsType, LocalDate startDate, LocalDate endDate, String createdBy) {
        try {
            log.info("开始生成统计数据，统计类型：{}，日期范围：{} - {}", statisticsType, startDate, endDate);

            List<Map<String, Object>> statisticsResults;
            
            // 根据统计类型执行不同的统计SQL
            if ("daily".equals(statisticsType)) {
                // 日统计：使用传入的日期，按经销商和日期双重分组
                if (startDate == null) {
                    throw new IllegalArgumentException("日统计需要提供统计日期");
                }
                
                // 先删除已存在的统计数据
                deleteByCondition(null, statisticsType, startDate, startDate);
                
                String startDateTime = startDate.atStartOfDay().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                String endDateTime = startDate.atTime(23, 59, 59).format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                statisticsResults = cpaBrandScoreStatisticsMapper.executeDailyStatistics(startDateTime, endDateTime);
                
            } else if ("weekly".equals(statisticsType)) {
                // 周统计：自动计算上周的开始和结束时间
                LocalDate lastWeekStart = LocalDate.now().minusWeeks(1).with(java.time.DayOfWeek.MONDAY);
                LocalDate lastWeekEnd = lastWeekStart.plusDays(6);
                
                log.info("周统计自动计算时间范围：{} - {}", lastWeekStart, lastWeekEnd);
                
                // 先删除已存在的统计数据
                deleteByCondition(null, statisticsType, lastWeekStart, lastWeekEnd);
                
                String startDateTime = lastWeekStart.atStartOfDay().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                String endDateTime = lastWeekEnd.atTime(23, 59, 59).format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                statisticsResults = cpaBrandScoreStatisticsMapper.executeDateRangeStatistics(startDateTime, endDateTime);
                
            } else if ("monthly".equals(statisticsType)) {
                // 月统计：自动计算上个月的开始和结束时间
                LocalDate lastMonthStart = LocalDate.now().minusMonths(1).withDayOfMonth(1);
                LocalDate lastMonthEnd = lastMonthStart.withDayOfMonth(lastMonthStart.lengthOfMonth());
                
                log.info("月统计自动计算时间范围：{} - {}", lastMonthStart, lastMonthEnd);
                
                // 先删除已存在的统计数据
                deleteByCondition(null, statisticsType, lastMonthStart, lastMonthEnd);
                
                String startDateTime = lastMonthStart.atStartOfDay().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                String endDateTime = lastMonthEnd.atTime(23, 59, 59).format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                statisticsResults = cpaBrandScoreStatisticsMapper.executeDateRangeStatistics(startDateTime, endDateTime);
                
            } else if ("total".equals(statisticsType)) {
                // 总计统计：统计所有历史数据
                // 先删除已存在的统计数据
                deleteByCondition(null, statisticsType, null, null);
                
                statisticsResults = cpaBrandScoreStatisticsMapper.executeTotalStatistics();
                
            } else {
                throw new IllegalArgumentException("不支持的统计类型：" + statisticsType);
            }
            
            // 转换为实体对象并保存
            LocalDate statisticsDate;
            if ("weekly".equals(statisticsType)) {
                // 周统计使用上周的结束日期作为统计日期
                statisticsDate = LocalDate.now().minusWeeks(1).with(java.time.DayOfWeek.MONDAY).plusDays(6);
            } else if ("monthly".equals(statisticsType)) {
                // 月统计使用上月的最后一天作为统计日期
                statisticsDate = LocalDate.now().minusMonths(1).withDayOfMonth(1).withDayOfMonth(
                        LocalDate.now().minusMonths(1).withDayOfMonth(1).lengthOfMonth());
            } else {
                // 日统计和总计统计使用传入的日期
                statisticsDate = endDate;
            }
            
            List<CpaBrandScoreStatistics> statisticsList = convertToStatisticsList(statisticsResults, statisticsDate, statisticsType, createdBy);
            boolean success = batchSave(statisticsList);
            
            if (success) {
                log.info("统计数据生成完成，统计类型：{}，统计日期：{}，生成记录数：{}", statisticsType, statisticsDate, statisticsList.size());
                return statisticsList.size();
            } else {
                log.error("统计数据保存失败，统计类型：{}", statisticsType);
                return 0;
            }
        } catch (Exception e) {
            log.error("生成统计数据失败", e);
            throw e;
        }
    }

    @Override
    public Map<String, Object> getStatisticsOverview(String statisticsType, LocalDate startDate, LocalDate endDate) {
        Map<String, Object> overview = new HashMap<>();
        
        try {
            // 获取统计数据列表
            List<CpaBrandScoreStatistics> statisticsList = getByDateRange(startDate, endDate, statisticsType);
            
            if (statisticsList.isEmpty()) {
                overview.put("totalDealers", 0);
                overview.put("totalRecords", 0);
                overview.put("averageScore", 0.0);
                overview.put("topDealer", null);
                return overview;
            }
            
            // 计算概览数据
            int totalDealers = (int) statisticsList.stream()
                    .map(CpaBrandScoreStatistics::getDealerCode)
                    .distinct()
                    .count();
            
            int totalRecords = statisticsList.stream()
                    .mapToInt(CpaBrandScoreStatistics::getTotalRecords)
                    .sum();
            
            double averageScore = statisticsList.stream()
                    .mapToDouble(s -> s.getAverageScorePercentage().doubleValue())
                    .average()
                    .orElse(0.0);
            
            // 获取得分最高的经销商
            CpaBrandScoreStatistics topDealer = statisticsList.stream()
                    .max((s1, s2) -> s1.getAverageScorePercentage().compareTo(s2.getAverageScorePercentage()))
                    .orElse(null);
            
            overview.put("totalDealers", totalDealers);
            overview.put("totalRecords", totalRecords);
            overview.put("averageScore", averageScore);
            overview.put("topDealer", topDealer);
            overview.put("statisticsCount", statisticsList.size());
            
            log.info("获取统计概览数据成功，经销商数：{}，总记录数：{}，平均得分：{}", 
                    totalDealers, totalRecords, averageScore);
            
        } catch (Exception e) {
            log.error("获取统计概览数据失败", e);
            throw e;
        }
        
        return overview;
    }

    /**
     * 根据条件查询统计数据（支持分页）
     * 
     * @param dealerCode 经销商编码
     * @param bigArea 大区
     * @param statisticsType 统计类型
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 统计数据列表
     */
    public List<CpaBrandScoreStatistics> getByCondition(String dealerCode, String bigArea, 
                                                       String statisticsType, LocalDate startDate, LocalDate endDate) {
        LambdaQueryWrapper<CpaBrandScoreStatistics> queryWrapper = new LambdaQueryWrapper<>();
        
        queryWrapper.eq(CpaBrandScoreStatistics::getIsDeleted, 0);
        
        if (dealerCode != null && !dealerCode.trim().isEmpty()) {
            queryWrapper.eq(CpaBrandScoreStatistics::getDealerCode, dealerCode);
        }
        
        if (bigArea != null && !bigArea.trim().isEmpty()) {
            queryWrapper.eq(CpaBrandScoreStatistics::getBigArea, bigArea);
        }
        
        if (statisticsType != null && !statisticsType.trim().isEmpty()) {
            queryWrapper.eq(CpaBrandScoreStatistics::getStatisticsType, statisticsType);
        }
        
        if (startDate != null) {
            queryWrapper.ge(CpaBrandScoreStatistics::getStatisticsDate, startDate);
        }
        
        if (endDate != null) {
            queryWrapper.le(CpaBrandScoreStatistics::getStatisticsDate, endDate);
        }
        
        queryWrapper.orderByDesc(CpaBrandScoreStatistics::getAverageScorePercentage)
                   .orderByDesc(CpaBrandScoreStatistics::getTotalScore);
        
        return list(queryWrapper);
    }

    /**
     * 将查询结果转换为统计实体列表
     * 
     * @param results 查询结果
     * @param statisticsDate 统计日期
     * @param statisticsType 统计类型
     * @param createdBy 创建人
     * @return 统计实体列表
     */
    private List<CpaBrandScoreStatistics> convertToStatisticsList(List<Map<String, Object>> results, 
                                                                 LocalDate statisticsDate, 
                                                                 String statisticsType, 
                                                                 String createdBy) {
        List<CpaBrandScoreStatistics> statisticsList = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();
        
        for (Map<String, Object> row : results) {
            CpaBrandScoreStatistics statistics = new CpaBrandScoreStatistics();
            
            statistics.setId(java.util.UUID.randomUUID().toString());
            statistics.setDealerCode((String) row.get("dealer_code"));
            statistics.setDealerName((String) row.get("dealer_name"));
            statistics.setBigArea((String) row.get("big_area"));
            
            // 对于日统计，使用查询结果中的日期；其他统计类型使用传入的日期
            if ("daily".equals(statisticsType) && row.get("statistics_date") != null) {
                if (row.get("statistics_date") instanceof java.sql.Date) {
                    statistics.setStatisticsDate(((java.sql.Date) row.get("statistics_date")).toLocalDate());
                } else {
                    statistics.setStatisticsDate(statisticsDate);
                }
            } else {
                statistics.setStatisticsDate(statisticsDate);
            }
            
            statistics.setStatisticsType(statisticsType);
            
            // 数值字段转换
            statistics.setTotalRecords(convertToInteger(row.get("daily_records")));
            statistics.setTotalScore(convertToInteger(row.get("daily_total_score")));
            statistics.setAverageScorePercentage(convertToBigDecimal(row.get("daily_average_score_percentage")));
            statistics.setPositiveCount(convertToInteger(row.get("daily_positive_count")));
            statistics.setNeutralCount(convertToInteger(row.get("daily_neutral_count")));
            statistics.setNegativeCount(convertToInteger(row.get("daily_negative_count")));
            statistics.setPositiveRate(convertToBigDecimal(row.get("daily_positive_rate")));
            statistics.setNeutralRate(convertToBigDecimal(row.get("daily_neutral_rate")));
            statistics.setNegativeRate(convertToBigDecimal(row.get("daily_negative_rate")));
            
            // 时间字段转换
            statistics.setEarliestInteraction(convertToLocalDateTime(row.get("daily_earliest_time")));
            statistics.setLatestInteraction(convertToLocalDateTime(row.get("daily_latest_time")));
            
            // 系统字段
            statistics.setCreatedAt(now);
            statistics.setUpdatedAt(now);
            statistics.setCreatedBy(createdBy != null ? createdBy : "system");
            statistics.setUpdatedBy(createdBy != null ? createdBy : "system");
            statistics.setIsDeleted(0);
            
            statisticsList.add(statistics);
        }
        
        return statisticsList;
    }

    /**
     * 类型转换辅助方法
     */
    private Integer convertToInteger(Object value) {
        if (value == null) return 0;
        if (value instanceof Number) {
            return ((Number) value).intValue();
        }
        return Integer.parseInt(value.toString());
    }

    private java.math.BigDecimal convertToBigDecimal(Object value) {
        if (value == null) return java.math.BigDecimal.ZERO;
        if (value instanceof Number) {
            return java.math.BigDecimal.valueOf(((Number) value).doubleValue());
        }
        return new java.math.BigDecimal(value.toString());
    }

    private LocalDateTime convertToLocalDateTime(Object value) {
        if (value == null) return null;
        if (value instanceof java.sql.Timestamp) {
            return ((java.sql.Timestamp) value).toLocalDateTime();
        }
        if (value instanceof java.sql.Date) {
            return ((java.sql.Date) value).toLocalDate().atStartOfDay();
        }
        return LocalDateTime.parse(value.toString());
    }
}
