package com.reading.platform.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.reading.platform.entity.*;
import com.reading.platform.mapper.*;
import com.reading.platform.service.AdminStatsService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

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

/**
 * 管理员统计服务实现类
 */
@Service
@RequiredArgsConstructor
public class AdminStatsServiceImpl implements AdminStatsService {

    private final TenantMapper tenantMapper;
    private final TeacherMapper teacherMapper;
    private final StudentMapper studentMapper;
    private final CourseMapper courseMapper;
    private final LessonMapper lessonMapper;

    @Override
    public Map<String, Object> getStats() {
        Map<String, Object> stats = new HashMap<>();

        long tenantCount = tenantMapper.selectCount(null);
        long activeTenantCount = tenantMapper.selectCount(
                new LambdaQueryWrapper<Tenant>().eq(Tenant::getStatus, "active"));
        long courseCount = courseMapper.selectCount(null);
        long publishedCourseCount = courseMapper.selectCount(
                new LambdaQueryWrapper<Course>().eq(Course::getStatus, "published"));

        // Monthly lessons (current month)
        LocalDate monthStart = LocalDate.now().withDayOfMonth(1);
        LocalDate monthEnd = LocalDate.now().withDayOfMonth(LocalDate.now().lengthOfMonth());
        long monthlyLessons = lessonMapper.selectCount(
                new LambdaQueryWrapper<Lesson>()
                        .ge(Lesson::getLessonDate, monthStart)
                        .le(Lesson::getLessonDate, monthEnd));

        stats.put("tenantCount", Math.toIntExact(tenantCount));
        stats.put("activeTenantCount", Math.toIntExact(activeTenantCount));
        stats.put("teacherCount", Math.toIntExact(teacherMapper.selectCount(null)));
        stats.put("studentCount", Math.toIntExact(studentMapper.selectCount(null)));
        stats.put("courseCount", Math.toIntExact(courseCount));
        stats.put("publishedCourseCount", Math.toIntExact(publishedCourseCount));
        stats.put("lessonCount", Math.toIntExact(lessonMapper.selectCount(null)));
        stats.put("monthlyLessons", Math.toIntExact(monthlyLessons));
        return stats;
    }

    @Override
    public List<Map<String, Object>> getTrendData() {
        List<Map<String, Object>> trend = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
        LocalDate now = LocalDate.now();

        for (int i = 5; i >= 0; i--) {
            LocalDate monthStart = now.minusMonths(i).withDayOfMonth(1);
            LocalDate monthEnd = monthStart.withDayOfMonth(monthStart.lengthOfMonth());

            long lessonCount = lessonMapper.selectCount(
                    new LambdaQueryWrapper<Lesson>()
                            .ge(Lesson::getLessonDate, monthStart)
                            .le(Lesson::getLessonDate, monthEnd));

            // Count tenants created up to this month end
            long tenantCount = tenantMapper.selectCount(
                    new LambdaQueryWrapper<Tenant>()
                            .le(Tenant::getCreatedAt, monthEnd.atTime(23, 59, 59)));

            // Count students created up to this month end
            long studentCount = studentMapper.selectCount(
                    new LambdaQueryWrapper<Student>()
                            .le(Student::getCreatedAt, monthEnd.atTime(23, 59, 59)));

            Map<String, Object> point = new HashMap<>();
            point.put("month", monthStart.format(formatter));
            point.put("tenantCount", Math.toIntExact(tenantCount));
            point.put("lessonCount", Math.toIntExact(lessonCount));
            point.put("studentCount", Math.toIntExact(studentCount));
            trend.add(point);
        }
        return trend;
    }

    @Override
    public List<Map<String, Object>> getActiveTenants(int limit) {
        LambdaQueryWrapper<Tenant> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Tenant::getStatus, "active")
               .orderByDesc(Tenant::getCreatedAt)
               .last("LIMIT " + limit);
        List<Tenant> tenants = tenantMapper.selectList(wrapper);
        return tenants.stream().map(t -> {
            Map<String, Object> map = new HashMap<>();
            map.put("id", t.getId());
            map.put("name", t.getName());
            map.put("code", t.getCode());
            map.put("status", t.getStatus());
            map.put("expireAt", t.getExpireAt());
            // Count teachers and students for this tenant
            long teacherCount = teacherMapper.selectCount(
                    new LambdaQueryWrapper<Teacher>().eq(Teacher::getTenantId, t.getId()));
            long studentCount = studentMapper.selectCount(
                    new LambdaQueryWrapper<Student>().eq(Student::getTenantId, t.getId()));
            long lessonCount = lessonMapper.selectCount(
                    new LambdaQueryWrapper<Lesson>().eq(Lesson::getTenantId, t.getId()));
            map.put("teacherCount", Math.toIntExact(teacherCount));
            map.put("studentCount", Math.toIntExact(studentCount));
            map.put("lessonCount", Math.toIntExact(lessonCount));
            return map;
        }).collect(Collectors.toList());
    }

    @Override
    public List<Map<String, Object>> getPopularCourses(int limit) {
        LambdaQueryWrapper<Course> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Course::getIsSystem, 1)
               .eq(Course::getStatus, "published")
               .orderByDesc(Course::getCreatedAt)
               .last("LIMIT " + limit);
        List<Course> courses = courseMapper.selectList(wrapper);
        return courses.stream().map(c -> {
            Map<String, Object> map = new HashMap<>();
            map.put("id", c.getId());
            map.put("name", c.getName());
            map.put("category", c.getCategory());
            map.put("status", c.getStatus());
            map.put("usageCount", c.getUsageCount() != null ? Math.toIntExact(c.getUsageCount()) : 0);
            map.put("teacherCount", c.getTeacherCount() != null ? Math.toIntExact(c.getTeacherCount()) : 0);
            return map;
        }).collect(Collectors.toList());
    }

    @Override
    public List<Map<String, Object>> getRecentActivities(int limit) {
        LambdaQueryWrapper<Lesson> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(Lesson::getCreatedAt).last("LIMIT " + limit);
        List<Lesson> lessons = lessonMapper.selectList(wrapper);
        return lessons.stream().map(l -> {
            Map<String, Object> map = new HashMap<>();
            map.put("id", l.getId());
            map.put("title", l.getTitle());
            map.put("lessonDate", l.getLessonDate());
            map.put("status", l.getStatus());
            return map;
        }).collect(Collectors.toList());
    }

    @Override
    public List<Map<String, Object>> getLessonTrend(Integer months) {
        int monthLimit = months != null ? months : 6;
        List<Map<String, Object>> trend = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
        LocalDate now = LocalDate.now();

        for (int i = monthLimit - 1; i >= 0; i--) {
            LocalDate monthStart = now.minusMonths(i).withDayOfMonth(1);
            LocalDate monthEnd = monthStart.withDayOfMonth(monthStart.lengthOfMonth());

            long lessonCount = lessonMapper.selectCount(
                    new LambdaQueryWrapper<Lesson>()
                            .ge(Lesson::getLessonDate, monthStart)
                            .le(Lesson::getLessonDate, monthEnd));

            Map<String, Object> point = new HashMap<>();
            point.put("month", monthStart.format(formatter));
            point.put("lessonCount", Math.toIntExact(lessonCount));
            trend.add(point);
        }
        return trend;
    }
}
