package com.lesingle.edu.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.lesingle.edu.dto.request.ActiveTenantsQueryRequest;
import com.lesingle.edu.dto.request.PopularCoursesQueryRequest;
import com.lesingle.edu.dto.response.ActiveTenantItemResponse;
import com.lesingle.edu.dto.response.PopularCourseItemResponse;
import com.lesingle.edu.dto.response.StatsResponse;
import com.lesingle.edu.dto.response.StatsTrendResponse;
import com.lesingle.edu.entity.CoursePackage;
import com.lesingle.edu.entity.Student;
import com.lesingle.edu.entity.Teacher;
import com.lesingle.edu.entity.Tenant;
import com.lesingle.edu.entity.Lesson;
import com.lesingle.edu.common.enums.LessonStatus;
import com.lesingle.edu.common.enums.TenantStatus;
import com.lesingle.edu.mapper.CoursePackageMapper;
import com.lesingle.edu.mapper.CourseLessonMapper;
import com.lesingle.edu.mapper.LessonMapper;
import com.lesingle.edu.mapper.StudentMapper;
import com.lesingle.edu.mapper.TeacherMapper;
import com.lesingle.edu.mapper.TenantMapper;
import com.lesingle.edu.mapper.StudentRecordMapper;
import com.lesingle.edu.service.StatsService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 统计服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class StatsServiceImpl implements StatsService {

    private final TenantMapper tenantMapper;
    private final TeacherMapper teacherMapper;
    private final StudentMapper studentMapper;
    private final CoursePackageMapper courseMapper;
    private final CourseLessonMapper courseLessonMapper;
    private final LessonMapper lessonMapper;
    private final StudentRecordMapper studentRecordMapper;

    // ==================== 常量定义 ====================
    /** 活跃教师统计时间窗口（天） */
    private static final int ACTIVE_TEACHER_WINDOW_DAYS = 30;

    /** 活跃租户 TOP 数量 */
    private static final int DEFAULT_TOP_LIMIT = 5;

    /** 活跃教师数权重 */
    private static final double WEIGHT_ACTIVE_TEACHER = 1.0;

    /** 完成课次数权重 */
    private static final double WEIGHT_COMPLETED_LESSON = 0.1;

    @Override
    public StatsResponse getStats() {
        log.info("获取统计数据");

        // 租户总数
        Long totalTenants = tenantMapper.selectCount(null);

        // 活跃租户数
        Long activeTenants = tenantMapper.selectCount(
                new LambdaQueryWrapper<Tenant>().eq(Tenant::getStatus, TenantStatus.ACTIVE.getCode())
        );

        // 教师总数
        Long totalTeachers = teacherMapper.selectCount(null);

        // 学生总数
        Long totalStudents = studentMapper.selectCount(null);

        // 课程总数
        Long totalCourses = courseMapper.selectCount(null);

        // 课时总数（course_lesson 表记录数）
        Long totalLessons = courseLessonMapper.selectCount(null);

        // 月授课次数：本月自然月内 COMPLETED 状态的 lesson 总数
        LocalDateTime monthStart = LocalDateTime.now().withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0);
        LocalDateTime monthEnd = monthStart.plusMonths(1);
        Long monthlyLessons = lessonMapper.selectCount(
                new LambdaQueryWrapper<Lesson>()
                        .eq(Lesson::getStatus, LessonStatus.COMPLETED.getCode())
                        .ge(Lesson::getEndDatetime, monthStart)
                        .lt(Lesson::getEndDatetime, monthEnd)
        );

        return StatsResponse.builder()
                .totalTenants(totalTenants)
                .activeTenants(activeTenants)
                .totalTeachers(totalTeachers)
                .totalStudents(totalStudents)
                .totalCourses(totalCourses)
                .totalLessons(totalLessons)
                .monthlyLessons(monthlyLessons)
                .build();
    }

    @Override
    public StatsTrendResponse getTrendData() {
        log.info("获取趋势数据");

        LocalDateTime now = LocalDateTime.now();
        List<String> dates = new ArrayList<>();
        List<Integer> lessonCounts = new ArrayList<>();
        List<Integer> studentCounts = new ArrayList<>();

        // 获取最近 7 天的趋势数据
        for (int i = 6; i >= 0; i--) {
            LocalDate date = now.minusDays(i).toLocalDate();
            dates.add(date.format(DateTimeFormatter.ofPattern("MM-dd")));

            // 当天时间范围
            LocalDateTime dayStart = date.atStartOfDay();
            LocalDateTime dayEnd = date.plusDays(1).atStartOfDay();

            // 当天完成的授课次数
            Long lessons = lessonMapper.selectCount(
                    new LambdaQueryWrapper<Lesson>()
                            .eq(Lesson::getStatus, LessonStatus.COMPLETED.getCode())
                            .ge(Lesson::getEndDatetime, dayStart)
                            .lt(Lesson::getEndDatetime, dayEnd)
            );
            lessonCounts.add(lessons != null ? lessons.intValue() : 0);

            // 当天活跃学生数（有完成课程记录的去重学生数）
            Long activeStudents = studentRecordMapper.countActiveStudents(dayStart, dayEnd);
            studentCounts.add(activeStudents != null ? activeStudents.intValue() : 0);
        }

        return StatsTrendResponse.builder()
                .dates(dates)
                .lessonCounts(lessonCounts)
                .studentCounts(studentCounts)
                .build();
    }

    @Override
    public List<ActiveTenantItemResponse> getActiveTenants(ActiveTenantsQueryRequest request) {
        int limit = request != null && request.getLimit() != null ? request.getLimit() : DEFAULT_TOP_LIMIT;

        // 计算时间窗口：近 30 天
        LocalDateTime windowStart = LocalDateTime.now().minusDays(ACTIVE_TEACHER_WINDOW_DAYS);

        // 1. 查询所有状态为 ACTIVE 的租户
        List<Tenant> tenants = tenantMapper.selectList(
                new LambdaQueryWrapper<Tenant>()
                        .eq(Tenant::getStatus, TenantStatus.ACTIVE.getCode())
        );

        // 2. 对每个租户统计活跃教师数和完成课次数
        List<ActiveTenantItemResponse> resultList = tenants.stream().map(tenant -> {
            // 2.1 查询该租户下近 30 天完成状态的课程记录
            List<Lesson> lessons = lessonMapper.selectList(
                    new LambdaQueryWrapper<Lesson>()
                            .eq(Lesson::getTenantId, tenant.getId())
                            .eq(Lesson::getStatus, LessonStatus.COMPLETED.getCode())
                            .ge(Lesson::getEndDatetime, windowStart)
                            .isNotNull(Lesson::getTeacherId)
            );

            // 2.2 去重统计活跃教师数（近 30 天有完成课程的老师数）
            long distinctTeacherCount = lessons.stream()
                    .map(Lesson::getTeacherId)
                    .filter(java.util.Objects::nonNull)
                    .distinct()
                    .count();

            // 2.3 统计完成课次数（近 30 天 COMPLETED 状态的 lesson 总数）
            long completedLessonCount = lessons.size();

            return ActiveTenantItemResponse.builder()
                    .tenantId(tenant.getId())
                    .tenantName(tenant.getName())
                    .activeTeacherCount((int) distinctTeacherCount)
                    .completedLessonCount((int) completedLessonCount)
                    .build();
        }).collect(Collectors.toList());

        // 3. 按加权分数降序排序：score = activeTeacherCount * 1.0 + completedLessonCount * 0.1
        resultList.sort((a, b) -> {
            double scoreA = a.getActiveTeacherCount() * WEIGHT_ACTIVE_TEACHER +
                           a.getCompletedLessonCount() * WEIGHT_COMPLETED_LESSON;
            double scoreB = b.getActiveTeacherCount() * WEIGHT_ACTIVE_TEACHER +
                           b.getCompletedLessonCount() * WEIGHT_COMPLETED_LESSON;
            return Double.compare(scoreB, scoreA); // 降序
        });

        // 4. 返回 TOP N
        return resultList.stream()
                .limit(limit)
                .collect(Collectors.toList());
    }

    @Override
    public List<PopularCourseItemResponse> getPopularCourses(PopularCoursesQueryRequest request) {
        log.info("获取热门课程，limit={}", request != null ? request.getLimit() : 10);

        int limit = request != null && request.getLimit() != null ? request.getLimit() : 10;

        // 查询使用次数最多的课程
        List<CoursePackage> courses = courseMapper.selectList(
                new LambdaQueryWrapper<CoursePackage>()
                        .eq(CoursePackage::getIsSystem, 1)
                        .orderByDesc(CoursePackage::getUsageCount)
                        .last("LIMIT " + limit)
        );

        return courses.stream().map(course -> PopularCourseItemResponse.builder()
                .courseId(course.getId())
                .courseName(course.getName())
                .usageCount(course.getUsageCount() != null ? course.getUsageCount() : 0)
                .teacherCount(course.getTeacherCount() != null ? course.getTeacherCount() : 0)
                .build()
        ).collect(Collectors.toList());
    }
}
