package com.lesingle.edu.service.impl;

import com.lesingle.edu.common.exception.BusinessException;
import com.lesingle.edu.dto.response.CoursePackageStatsResponse;
import com.lesingle.edu.entity.CoursePackage;
import com.lesingle.edu.mapper.CoursePackageMapper;
import com.lesingle.edu.mapper.CoursePackageStatsMapper;
import com.lesingle.edu.service.CoursePackageStatsService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

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

/**
 * 课程包数据统计服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CoursePackageStatsServiceImpl implements CoursePackageStatsService {

    private final CoursePackageMapper coursePackageMapper;
    private final CoursePackageStatsMapper statsMapper;

    private static final int TREND_DAYS = 14;
    private static final int RECENT_LESSONS_LIMIT = 10;

    @Override
    public CoursePackageStatsResponse getStats(Long coursePackageId) {
        CoursePackage pkg = coursePackageMapper.selectById(coursePackageId);
        if (pkg == null) {
            throw new BusinessException("课程包不存在: " + coursePackageId);
        }

        Map<String, Object> overview = statsMapper.getOverviewStats(coursePackageId);
        LocalDate endDate = LocalDate.now();
        LocalDate startDate = endDate.minusDays(TREND_DAYS);
        List<Map<String, Object>> trendRaw = statsMapper.getLessonTrend(coursePackageId, startDate, endDate);
        Map<String, Object> feedbackRaw = statsMapper.getFeedbackDistribution(coursePackageId);
        List<Map<String, Object>> recentRaw = statsMapper.getRecentLessons(coursePackageId, RECENT_LESSONS_LIMIT);
        Map<String, Object> studentPerfRaw = statsMapper.getStudentPerformance(coursePackageId);

        return CoursePackageStatsResponse.builder()
                .courseName(pkg.getName())
                .totalLessons(getInt(overview, "totalLessons"))
                .totalTeachers(getInt(overview, "totalTeachers"))
                .totalStudents(getInt(overview, "totalStudents"))
                .avgRating(getBigDecimal(overview, "avgRating"))
                .lessonTrend(toLessonTrend(trendRaw))
                .feedbackDistribution(toFeedbackDistribution(feedbackRaw))
                .recentLessons(toRecentLessons(recentRaw))
                .studentPerformance(toStudentPerformance(studentPerfRaw))
                .build();
    }

    @Override
    public Map<Long, PackageStats> getBatchStats(List<Long> coursePackageIds) {
        if (coursePackageIds == null || coursePackageIds.isEmpty()) {
            return Map.of();
        }
        List<Map<String, Object>> rows = statsMapper.getBatchOverviewStats(coursePackageIds);
        Map<Long, PackageStats> result = new HashMap<>();
        for (Map<String, Object> row : rows) {
            Long id = getLong(row, "coursePackageId");
            if (id != null) {
                result.put(id, new PackageStats(
                        getInt(row, "usageCount"),
                        getInt(row, "teacherCount"),
                        getBigDecimal(row, "avgRating")
                ));
            }
        }
        // 确保所有 ID 都有条目（无数据时为 0）
        for (Long id : coursePackageIds) {
            result.putIfAbsent(id, new PackageStats(0, 0, BigDecimal.ZERO));
        }
        return result;
    }

    private List<CoursePackageStatsResponse.LessonTrendItem> toLessonTrend(List<Map<String, Object>> raw) {
        if (raw == null) return List.of();
        return raw.stream()
                .map(r -> CoursePackageStatsResponse.LessonTrendItem.builder()
                        .date(getString(r, "date"))
                        .count(getInt(r, "count"))
                        .build())
                .collect(Collectors.toList());
    }

    private CoursePackageStatsResponse.FeedbackDistribution toFeedbackDistribution(Map<String, Object> raw) {
        if (raw == null || getInt(raw, "totalFeedbacks") == 0) {
            return null;
        }
        return CoursePackageStatsResponse.FeedbackDistribution.builder()
                .designQuality(getBigDecimal(raw, "designQuality"))
                .participation(getBigDecimal(raw, "participation"))
                .goalAchievement(getBigDecimal(raw, "goalAchievement"))
                .totalFeedbacks(getInt(raw, "totalFeedbacks"))
                .build();
    }

    private List<CoursePackageStatsResponse.RecentLessonItem> toRecentLessons(List<Map<String, Object>> raw) {
        if (raw == null) return List.of();
        List<CoursePackageStatsResponse.RecentLessonItem> items = new ArrayList<>();
        for (Map<String, Object> r : raw) {
            Object startDt = r.get("startDatetime");
            String startDatetime = startDt != null ? startDt.toString() : null;
            items.add(CoursePackageStatsResponse.RecentLessonItem.builder()
                    .teacher(CoursePackageStatsResponse.TeacherInfo.builder()
                            .id(getLong(r, "teacherId"))
                            .name(getString(r, "teacherName"))
                            .build())
                    .classInfo(CoursePackageStatsResponse.ClassInfo.builder()
                            .id(getLong(r, "classId"))
                            .name(getString(r, "className"))
                            .build())
                    .startDatetime(startDatetime)
                    .actualDuration(getInt(r, "actualDuration"))
                    .duration(null)
                    .status(getString(r, "status"))
                    .build());
        }
        return items;
    }

    private CoursePackageStatsResponse.StudentPerformance toStudentPerformance(Map<String, Object> raw) {
        if (raw == null) return null;
        return CoursePackageStatsResponse.StudentPerformance.builder()
                .avgFocus(getBigDecimal(raw, "avgFocus"))
                .avgParticipation(getBigDecimal(raw, "avgParticipation"))
                .avgInterest(getBigDecimal(raw, "avgInterest"))
                .avgUnderstanding(getBigDecimal(raw, "avgUnderstanding"))
                .build();
    }

    private static int getInt(Map<String, Object> m, String key) {
        Object v = m != null ? m.get(key) : null;
        if (v == null) return 0;
        if (v instanceof Number) return ((Number) v).intValue();
        try {
            return Integer.parseInt(v.toString());
        } catch (NumberFormatException e) {
            return 0;
        }
    }

    private static Long getLong(Map<String, Object> m, String key) {
        Object v = m != null ? m.get(key) : null;
        if (v == null) return null;
        if (v instanceof Number) return ((Number) v).longValue();
        try {
            return Long.parseLong(v.toString());
        } catch (NumberFormatException e) {
            return null;
        }
    }

    private static String getString(Map<String, Object> m, String key) {
        Object v = m != null ? m.get(key) : null;
        return v != null ? v.toString() : null;
    }

    private static BigDecimal getBigDecimal(Map<String, Object> m, String key) {
        Object v = m != null ? m.get(key) : null;
        if (v == null) return BigDecimal.ZERO;
        if (v instanceof BigDecimal) return (BigDecimal) v;
        if (v instanceof Number) return BigDecimal.valueOf(((Number) v).doubleValue()).setScale(2, RoundingMode.HALF_UP);
        try {
            return new BigDecimal(v.toString()).setScale(2, RoundingMode.HALF_UP);
        } catch (NumberFormatException e) {
            return BigDecimal.ZERO;
        }
    }
}
