package com.reading.platform.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.reading.platform.common.enums.ErrorCode;
import com.reading.platform.common.exception.BusinessException;
import com.reading.platform.common.util.PageUtils;
import com.reading.platform.dto.request.*;
import com.reading.platform.entity.*;
import com.reading.platform.mapper.*;
import com.reading.platform.service.TaskService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

@Service
@Slf4j
@RequiredArgsConstructor
public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements TaskService {

    private final TaskMapper taskMapper;
    private final TaskTargetMapper taskTargetMapper;
    private final TaskCompletionMapper taskCompletionMapper;
    private final TaskTemplateMapper taskTemplateMapper;
    private final ClazzMapper classMapper;
    private final StudentClassHistoryMapper studentClassHistoryMapper;

    @Override
    @Transactional
    public Task createTask(String tenantId, String creatorId, String creatorRole, TaskCreateRequest request) {
        Task task = new Task();
        task.setTenantId(tenantId);
        task.setTitle(request.getTitle());
        task.setDescription(request.getDescription());
        task.setType(request.getType() != null ? request.getType() : "homework");
        task.setCourseId(request.getCourseId());
        task.setCreatorId(creatorId);
        task.setCreatorRole(creatorRole);
        task.setStartDate(request.getStartDate());
        task.setDueDate(request.getDueDate());
        task.setStatus("pending");
        task.setAttachments(request.getAttachments());

        taskMapper.insert(task);

        // Create task targets
        if (request.getTargetIds() != null && !request.getTargetIds().isEmpty()) {
            for (String targetId : request.getTargetIds()) {
                TaskTarget target = new TaskTarget();
                target.setTaskId(task.getId());
                target.setTargetType(request.getTargetType() != null ? request.getTargetType() : "class");
                target.setTargetId(targetId);
                taskTargetMapper.insert(target);
            }
        }

        return task;
    }

    @Override
    @Transactional
    public Task updateTask(String id, TaskUpdateRequest request) {
        Task task = getTaskById(id);

        if (StringUtils.hasText(request.getTitle())) {
            task.setTitle(request.getTitle());
        }
        if (request.getDescription() != null) {
            task.setDescription(request.getDescription());
        }
        if (request.getType() != null) {
            task.setType(request.getType());
        }
        if (request.getStartDate() != null) {
            task.setStartDate(request.getStartDate());
        }
        if (request.getDueDate() != null) {
            task.setDueDate(request.getDueDate());
        }
        if (StringUtils.hasText(request.getStatus())) {
            task.setStatus(request.getStatus());
        }
        if (request.getAttachments() != null) {
            task.setAttachments(request.getAttachments());
        }

        taskMapper.updateById(task);
        return task;
    }

    @Override
    public Task getTaskById(String id) {
        Task task = taskMapper.selectById(id);
        if (task == null) {
            throw new BusinessException(ErrorCode.DATA_NOT_FOUND, "Task not found");
        }
        return task;
    }

    @Override
    public Page<Task> getTaskPage(String tenantId, Integer pageNum, Integer pageSize, String keyword, String type, String status) {
        Page<Task> page = PageUtils.of(pageNum, pageSize);
        LambdaQueryWrapper<Task> wrapper = new LambdaQueryWrapper<>();

        wrapper.eq(Task::getTenantId, tenantId);

        if (StringUtils.hasText(keyword)) {
            wrapper.like(Task::getTitle, keyword);
        }
        if (StringUtils.hasText(type)) {
            wrapper.eq(Task::getType, type);
        }
        if (StringUtils.hasText(status)) {
            wrapper.eq(Task::getStatus, status);
        }
        wrapper.orderByDesc(Task::getCreatedAt);

        return taskMapper.selectPage(page, wrapper);
    }

    @Override
    public Page<Task> getTasksByStudentId(String studentId, Integer pageNum, Integer pageSize, String status) {
        Page<Task> page = PageUtils.of(pageNum, pageSize);

        // Get task IDs from task_completions for this student
        List<TaskCompletion> completions = taskCompletionMapper.selectList(
                new LambdaQueryWrapper<TaskCompletion>().eq(TaskCompletion::getStudentId, studentId)
        );

        if (completions.isEmpty()) {
            return page;
        }

        List<String> taskIds = completions.stream()
                .map(TaskCompletion::getTaskId)
                .toList();

        LambdaQueryWrapper<Task> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Task::getId, taskIds);

        if (StringUtils.hasText(status)) {
            wrapper.eq(Task::getStatus, status);
        }
        wrapper.orderByDesc(Task::getCreatedAt);

        return taskMapper.selectPage(page, wrapper);
    }

    @Override
    @Transactional
    public void deleteTask(String id) {
        getTaskById(id);
        taskMapper.deleteById(id);
    }

    @Override
    @Transactional
    public void completeTask(String taskId, String studentId, String content, String attachments) {
        TaskCompletion completion = taskCompletionMapper.selectOne(
                new LambdaQueryWrapper<TaskCompletion>()
                        .eq(TaskCompletion::getTaskId, taskId)
                        .eq(TaskCompletion::getStudentId, studentId)
        );

        if (completion == null) {
            completion = new TaskCompletion();
            completion.setTaskId(taskId);
            completion.setStudentId(studentId);
            completion.setStatus("completed");
            completion.setCompletedAt(LocalDateTime.now());
            completion.setContent(content);
            completion.setAttachments(attachments);
            taskCompletionMapper.insert(completion);
        } else {
            completion.setStatus("completed");
            completion.setCompletedAt(LocalDateTime.now());
            completion.setContent(content);
            completion.setAttachments(attachments);
            taskCompletionMapper.updateById(completion);
        }
    }

    @Override
    public List<Task> getTasksByClassId(String classId) {
        List<TaskTarget> targets = taskTargetMapper.selectList(
                new LambdaQueryWrapper<TaskTarget>()
                        .eq(TaskTarget::getTargetType, "class")
                        .eq(TaskTarget::getTargetId, classId)
        );

        if (targets.isEmpty()) {
            return new ArrayList<>();
        }

        List<String> taskIds = targets.stream()
                .map(TaskTarget::getTaskId)
                .toList();

        return taskMapper.selectList(
                new LambdaQueryWrapper<Task>()
                        .in(Task::getId, taskIds)
                        .orderByDesc(Task::getCreatedAt)
        );
    }

    // ==================== 任务统计 ====================

    @Override
    public Map<String, Object> getTaskStats(String tenantId) {
        // 统计任务总数
        long totalTasks = taskMapper.selectCount(new LambdaQueryWrapper<Task>().eq(Task::getTenantId, tenantId));

        // 统计已发布的任务数
        long publishedTasks = taskMapper.selectCount(new LambdaQueryWrapper<Task>()
                .eq(Task::getTenantId, tenantId).eq(Task::getStatus, "published"));

        // 统计完成情况
        long completedTasks = taskCompletionMapper.selectCount(new LambdaQueryWrapper<TaskCompletion>()
                .eq(TaskCompletion::getStatus, "completed"));

        long inProgressTasks = taskCompletionMapper.selectCount(new LambdaQueryWrapper<TaskCompletion>()
                .eq(TaskCompletion::getStatus, "in_progress"));

        long pendingCount = taskCompletionMapper.selectCount(new LambdaQueryWrapper<TaskCompletion>()
                .eq(TaskCompletion::getStatus, "pending"));

        long totalCompletions = taskCompletionMapper.selectCount(new LambdaQueryWrapper<TaskCompletion>());

        int completionRate = totalCompletions > 0 ? (int) ((completedTasks * 100) / totalCompletions) : 0;

        Map<String, Object> result = new HashMap<>();
        result.put("totalTasks", Math.toIntExact(totalTasks));
        result.put("publishedTasks", Math.toIntExact(publishedTasks));
        result.put("completedTasks", Math.toIntExact(completedTasks));
        result.put("inProgressTasks", Math.toIntExact(inProgressTasks));
        result.put("pendingCount", Math.toIntExact(pendingCount));
        result.put("totalCompletions", Math.toIntExact(totalCompletions));
        result.put("completionRate", completionRate);

        return result;
    }

    @Override
    public Map<String, Object> getStatsByType(String tenantId) {
        log.info("getStatsByType called with tenantId: {}", tenantId);
        List<Task> tasks = taskMapper.selectList(new LambdaQueryWrapper<Task>().eq(Task::getTenantId, tenantId));
        log.info("Found {} tasks for tenant {}", tasks.size(), tenantId);

        Map<String, Map<String, Object>> typeStats = new HashMap<>();

        for (Task task : tasks) {
            String type = task.getType() != null ? task.getType() : "homework";

            if (!typeStats.containsKey(type)) {
                typeStats.put(type, new HashMap<>());
                typeStats.get(type).put("total", 0);
                typeStats.get(type).put("completed", 0);
            }

            // 统计该任务的完成情况
            long completions = taskCompletionMapper.selectCount(new LambdaQueryWrapper<TaskCompletion>()
                    .eq(TaskCompletion::getTaskId, task.getId()));
            long completed = taskCompletionMapper.selectCount(new LambdaQueryWrapper<TaskCompletion>()
                    .eq(TaskCompletion::getTaskId, task.getId()).eq(TaskCompletion::getStatus, "completed"));

            int currentTotal = (Integer) typeStats.get(type).get("total");
            int currentCompleted = (Integer) typeStats.get(type).get("completed");
            typeStats.get(type).put("total", currentTotal + Math.toIntExact(completions));
            typeStats.get(type).put("completed", currentCompleted + Math.toIntExact(completed));
        }

        // 计算完成率
        for (Map<String, Object> stat : typeStats.values()) {
            int total = (Integer) stat.get("total");
            int completed = (Integer) stat.get("completed");
            stat.put("rate", total > 0 ? (int) ((completed * 100) / total) : 0);
        }

        log.info("Returning stats: {}", typeStats);
        // 转换类型：Map<String, Map<String, Object>> -> Map<String, Object>
        return new HashMap<>(typeStats);
    }

    @Override
    public List<Map<String, Object>> getStatsByClass(String tenantId) {
        log.info("getStatsByClass called with tenantId: {}", tenantId);
        List<Clazz> classes = classMapper.selectList(new LambdaQueryWrapper<Clazz>().eq(Clazz::getTenantId, tenantId));
        log.info("Found {} classes for tenant {}", classes.size(), tenantId);

        List<Map<String, Object>> classStats = new ArrayList<>();

        for (Clazz cls : classes) {
            // 获取班级学生的任务完成记录（通过 student_class_history 关联）
            List<StudentClassHistory> histories = studentClassHistoryMapper.selectList(
                    new LambdaQueryWrapper<StudentClassHistory>()
                            .eq(StudentClassHistory::getClassId, cls.getId())
                            .eq(StudentClassHistory::getStatus, "active")
            );

            if (histories.isEmpty()) {
                continue;
            }

            List<String> studentIds = histories.stream()
                    .map(StudentClassHistory::getStudentId)
                    .toList();

            if (studentIds.isEmpty()) {
                continue;
            }

            long completions = taskCompletionMapper.selectCount(new LambdaQueryWrapper<TaskCompletion>()
                    .in(TaskCompletion::getStudentId, studentIds));
            long completed = taskCompletionMapper.selectCount(new LambdaQueryWrapper<TaskCompletion>()
                    .in(TaskCompletion::getStudentId, studentIds).eq(TaskCompletion::getStatus, "completed"));

            int rate = completions > 0 ? (int) ((completed * 100) / completions) : 0;

            Map<String, Object> stat = new HashMap<>();
            stat.put("classId", cls.getId());
            stat.put("className", cls.getName());
            stat.put("grade", cls.getGrade());
            stat.put("total", Math.toIntExact(completions));
            stat.put("completed", Math.toIntExact(completed));
            stat.put("rate", rate);

            if (completions > 0) {
                classStats.add(stat);
            }
        }

        log.info("Returning class stats: {}", classStats);
        return classStats;
    }

    @Override
    public List<Map<String, Object>> getMonthlyStats(String tenantId, Integer months) {
        months = months != null ? months : 6;
        LocalDate now = LocalDate.now();
        LocalDate startDate = now.minusMonths(months - 1).withDayOfMonth(1);

        List<Map<String, Object>> monthlyData = new ArrayList<>();

        // 初始化月份数据
        for (int i = 0; i < months; i++) {
            LocalDate date = startDate.plusMonths(i);
            String key = String.format("%04d-%02d", date.getYear(), date.getMonthValue());

            Map<String, Object> data = new HashMap<>();
            data.put("month", key);
            data.put("tasks", 0);
            data.put("completions", 0);
            data.put("completed", 0);
            monthlyData.add(data);
        }

        // 统计每月的任务数
        List<Task> tasks = taskMapper.selectList(new LambdaQueryWrapper<Task>()
                .eq(Task::getTenantId, tenantId)
                .ge(Task::getCreatedAt, startDate.atStartOfDay()));

        for (Task task : tasks) {
            String month = String.format("%04d-%02d", task.getCreatedAt().getYear(), task.getCreatedAt().getMonthValue());
            for (Map<String, Object> data : monthlyData) {
                if (data.get("month").equals(month)) {
                    int currentTasks = (Integer) data.get("tasks");
                    data.put("tasks", currentTasks + 1);
                    break;
                }
            }
        }

        // 统计每月的完成情况
        for (Map<String, Object> data : monthlyData) {
            String month = (String) data.get("month");
            int year = Integer.parseInt(month.substring(0, 4));
            int monthNum = Integer.parseInt(month.substring(5, 7));

            LocalDateTime startOfMonth = LocalDateTime.of(year, monthNum, 1, 0, 0);
            LocalDateTime endOfMonth = startOfMonth.plusMonths(1);

            long completions = taskCompletionMapper.selectCount(new LambdaQueryWrapper<TaskCompletion>()
                    .ge(TaskCompletion::getCreatedAt, startOfMonth)
                    .lt(TaskCompletion::getCreatedAt, endOfMonth));

            long completed = taskCompletionMapper.selectCount(new LambdaQueryWrapper<TaskCompletion>()
                    .ge(TaskCompletion::getCreatedAt, startOfMonth)
                    .lt(TaskCompletion::getCreatedAt, endOfMonth)
                    .eq(TaskCompletion::getStatus, "completed"));

            data.put("completions", Math.toIntExact(completions));
            data.put("completed", Math.toIntExact(completed));
        }

        return monthlyData;
    }

    @Override
    public Page<TaskCompletion> getTaskCompletions(String tenantId, String taskId, Integer pageNum, Integer pageSize, String status) {
        Page<TaskCompletion> page = PageUtils.of(pageNum, pageSize);

        LambdaQueryWrapper<TaskCompletion> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TaskCompletion::getTaskId, taskId);

        // 通过 taskId 获取 task，验证 tenantId
        Task task = taskMapper.selectById(taskId);
        if (task == null || !task.getTenantId().equals(tenantId)) {
            throw new BusinessException(ErrorCode.DATA_NOT_FOUND, "任务不存在或无权限访问");
        }

        if (StringUtils.hasText(status)) {
            wrapper.eq(TaskCompletion::getStatus, status);
        }

        return taskCompletionMapper.selectPage(page, wrapper);
    }

    @Override
    @Transactional
    public TaskCompletion updateTaskCompletion(String tenantId, String taskId, String studentId, String status, String feedback) {
        // 验证任务属于该租户
        Task task = taskMapper.selectById(taskId);
        if (task == null || !task.getTenantId().equals(tenantId)) {
            throw new BusinessException(ErrorCode.DATA_NOT_FOUND, "任务不存在或无权限访问");
        }

        TaskCompletion completion = taskCompletionMapper.selectOne(
                new LambdaQueryWrapper<TaskCompletion>()
                        .eq(TaskCompletion::getTaskId, taskId)
                        .eq(TaskCompletion::getStudentId, studentId)
        );

        if (completion == null) {
            throw new BusinessException(ErrorCode.DATA_NOT_FOUND, "任务完成记录不存在");
        }

        completion.setStatus(status);
        if ("completed".equals(status)) {
            completion.setCompletedAt(LocalDateTime.now());
        }
        if (feedback != null) {
            completion.setFeedback(feedback);
        }

        taskCompletionMapper.updateById(completion);
        return completion;
    }

    // ==================== 任务模板 ====================

    @Override
    public Page<TaskTemplate> getTemplatePage(String tenantId, Integer pageNum, Integer pageSize, String keyword, String type) {
        Page<TaskTemplate> page = PageUtils.of(pageNum, pageSize);

        LambdaQueryWrapper<TaskTemplate> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TaskTemplate::getTenantId, tenantId);

        if (StringUtils.hasText(keyword)) {
            wrapper.and(w -> w.like(TaskTemplate::getName, keyword)
                    .or().like(TaskTemplate::getDescription, keyword));
        }

        if (StringUtils.hasText(type)) {
            wrapper.eq(TaskTemplate::getType, type);
        }

        wrapper.orderByDesc(TaskTemplate::getCreatedAt);

        return taskTemplateMapper.selectPage(page, wrapper);
    }

    @Override
    public TaskTemplate getTemplateById(String tenantId, String id) {
        TaskTemplate template = taskTemplateMapper.selectById(id);
        if (template == null || !template.getTenantId().equals(tenantId)) {
            throw new BusinessException(ErrorCode.DATA_NOT_FOUND, "模板不存在或无权限访问");
        }
        return template;
    }

    @Override
    public TaskTemplate getDefaultTemplate(String tenantId, String taskType) {
        // 优先查找公共模板，再查找租户的默认模板
        TaskTemplate template = taskTemplateMapper.selectOne(new LambdaQueryWrapper<TaskTemplate>()
                .eq(TaskTemplate::getType, taskType)
                .eq(TaskTemplate::getIsPublic, 1)
                .last("LIMIT 1"));

        if (template == null) {
            template = taskTemplateMapper.selectOne(new LambdaQueryWrapper<TaskTemplate>()
                    .eq(TaskTemplate::getTenantId, tenantId)
                    .eq(TaskTemplate::getType, taskType)
                    .last("LIMIT 1"));
        }

        return template;
    }

    @Override
    @Transactional
    public TaskTemplate createTemplate(String tenantId, String creatorId, TaskTemplateCreateRequest request) {
        TaskTemplate template = new TaskTemplate();
        template.setTenantId(tenantId);
        template.setName(request.getName());
        template.setDescription(request.getDescription());
        template.setType(request.getType() != null ? request.getType() : "homework");
        template.setContent(request.getContent());
        template.setIsPublic(request.getIsPublic() != null ? request.getIsPublic() : 0);

        taskTemplateMapper.insert(template);
        return template;
    }

    @Override
    @Transactional
    public TaskTemplate updateTemplate(String tenantId, String id, TaskTemplateUpdateRequest request) {
        TaskTemplate template = getTemplateById(tenantId, id);

        if (StringUtils.hasText(request.getName())) {
            template.setName(request.getName());
        }
        if (request.getDescription() != null) {
            template.setDescription(request.getDescription());
        }
        if (request.getType() != null) {
            template.setType(request.getType());
        }
        if (request.getContent() != null) {
            template.setContent(request.getContent());
        }
        if (request.getIsPublic() != null) {
            template.setIsPublic(request.getIsPublic());
        }

        taskTemplateMapper.updateById(template);
        return template;
    }

    @Override
    @Transactional
    public void deleteTemplate(String tenantId, String id) {
        getTemplateById(tenantId, id);
        taskTemplateMapper.deleteById(id);
    }

    @Override
    @Transactional
    public Task createTaskFromTemplate(String tenantId, String creatorId, String creatorRole, CreateTaskFromTemplateRequest request) {
        // 获取模板
        TaskTemplate template = getTemplateById(tenantId, request.getTemplateId());

        // 创建任务
        Task task = new Task();
        task.setTenantId(tenantId);
        task.setTitle(template.getName());
        task.setDescription(template.getDescription());
        task.setType(template.getType());
        task.setCreatorId(creatorId);
        task.setCreatorRole(creatorRole);
        task.setStartDate(request.getStartDate());
        task.setDueDate(request.getEndDate());
        task.setStatus("published");

        taskMapper.insert(task);

        // 创建任务目标和完成记录
        for (String targetId : request.getTargetIds()) {
            TaskTarget target = new TaskTarget();
            target.setTaskId(task.getId());
            target.setTargetType(request.getTargetType() != null ? request.getTargetType() : "class");
            target.setTargetId(targetId);
            taskTargetMapper.insert(target);

            // 如果是班级，为所有学生创建完成记录
            if ("class".equals(request.getTargetType())) {
                // 通过 student_class_history 获取班级中的学生
                List<StudentClassHistory> histories = studentClassHistoryMapper.selectList(
                        new LambdaQueryWrapper<StudentClassHistory>()
                                .eq(StudentClassHistory::getClassId, targetId)
                                .eq(StudentClassHistory::getStatus, "active")
                );

                List<String> studentIds = histories.stream()
                        .map(StudentClassHistory::getStudentId)
                        .toList();

                for (String studentId : studentIds) {
                    TaskCompletion completion = new TaskCompletion();
                    completion.setTaskId(task.getId());
                    completion.setStudentId(studentId);
                    completion.setStatus("pending");
                    taskCompletionMapper.insert(completion);
                }
            } else {
                // 如果是学生，直接创建完成记录
                TaskCompletion completion = new TaskCompletion();
                completion.setTaskId(task.getId());
                completion.setStudentId(targetId);
                completion.setStatus("pending");
                taskCompletionMapper.insert(completion);
            }
        }

        return task;
    }

    @Override
    public TaskCompletion getTaskCompletion(String taskId, String studentId) {
        return taskCompletionMapper.selectOne(
                new LambdaQueryWrapper<TaskCompletion>()
                        .eq(TaskCompletion::getTaskId, taskId)
                        .eq(TaskCompletion::getStudentId, studentId)
        );
    }

    @Override
    public Page<Task> getUpcomingTasks(String tenantId, Integer pageNum, Integer pageSize, Integer days) {
        int dayLimit = days != null ? days : 7; // 默认 7 天

        LambdaQueryWrapper<Task> wrapper = new LambdaQueryWrapper<Task>()
                .eq(Task::getTenantId, tenantId)
                .in(Task::getStatus, "published", "in_progress")
                .le(Task::getDueDate, LocalDateTime.now().plusDays(dayLimit))
                .orderByDesc(Task::getDueDate);

        return taskMapper.selectPage(new Page<>(pageNum, pageSize), wrapper);
    }

    @Override
    public void sendTaskReminder(String taskId) {
        Task task = taskMapper.selectById(taskId);
        if (task == null) {
            throw new RuntimeException("任务不存在");
        }

        // TODO: 发送通知（邮件、短信等）
        // 这里可以集成通知服务，发送提醒给未完成的任务参与者
        log.info("发送任务提醒：任务 ID={}, 任务名称={}", taskId, task.getName());
    }

}
