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.dto.request.SchedulePlanCreateRequest;
import com.reading.platform.dto.request.ScheduleTemplateApplyRequest;
import com.reading.platform.entity.SchedulePlan;
import com.reading.platform.entity.ScheduleTemplate;
import com.reading.platform.mapper.SchedulePlanMapper;
import com.reading.platform.mapper.ScheduleTemplateMapper;
import com.reading.platform.service.ScheduleService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.WeekFields;
import java.util.*;

/**
 * 课表服务实现类
 */
@Service
@RequiredArgsConstructor
public class ScheduleServiceImpl extends ServiceImpl<SchedulePlanMapper, SchedulePlan> implements ScheduleService {

    private final SchedulePlanMapper schedulePlanMapper;
    private final ScheduleTemplateMapper scheduleTemplateMapper;

    @Override
    public Page<SchedulePlan> getSchedulePlans(int pageNum, int pageSize, String tenantId, String classId) {
        Page<SchedulePlan> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<SchedulePlan> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SchedulePlan::getTenantId, tenantId);
        if (classId != null) {
            wrapper.eq(SchedulePlan::getClassId, classId);
        }
        wrapper.orderByDesc(SchedulePlan::getCreatedAt);
        return schedulePlanMapper.selectPage(page, wrapper);
    }

    @Override
    public Page<SchedulePlan> getSchedulePlans(int pageNum, int pageSize, String tenantId, String classId, LocalDate startDate, LocalDate endDate) {
        Page<SchedulePlan> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<SchedulePlan> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SchedulePlan::getTenantId, tenantId);
        if (classId != null) {
            wrapper.eq(SchedulePlan::getClassId, classId);
        }
        if (startDate != null) {
            wrapper.ge(SchedulePlan::getStartDate, startDate);
        }
        if (endDate != null) {
            wrapper.le(SchedulePlan::getEndDate, endDate);
        }
        wrapper.orderByDesc(SchedulePlan::getCreatedAt);
        return schedulePlanMapper.selectPage(page, wrapper);
    }

    @Override
    public SchedulePlan getSchedulePlanById(String id) {
        SchedulePlan plan = schedulePlanMapper.selectById(id);
        if (plan == null) {
            throw new BusinessException(ErrorCode.DATA_NOT_FOUND, "Schedule plan not found");
        }
        return plan;
    }

    @Override
    public SchedulePlan createSchedulePlan(String tenantId, SchedulePlan plan) {
        plan.setTenantId(tenantId);
        schedulePlanMapper.insert(plan);
        return plan;
    }

    @Override
    public SchedulePlan createSchedulePlan(String tenantId, String userId, SchedulePlanCreateRequest request) {
        SchedulePlan plan = new SchedulePlan();
        plan.setTenantId(tenantId);
        plan.setClassId(request.getClassId());
        plan.setCourseId(request.getCourseId());
        plan.setTeacherId(request.getTeacherId());
        plan.setDayOfWeek(request.getDayOfWeek());
        plan.setPeriod(request.getPeriod());
        plan.setStartTime(request.getStartTime());
        plan.setEndTime(request.getEndTime());
        plan.setLocation(request.getLocation());
        plan.setNote(request.getNote());
        plan.setStartDate(request.getStartDate());
        plan.setEndDate(request.getEndDate());
        plan.setStatus("active");

        schedulePlanMapper.insert(plan);
        return plan;
    }

    @Override
    public SchedulePlan updateSchedulePlan(String id, SchedulePlan plan) {
        SchedulePlan existing = getSchedulePlanById(id);
        plan.setId(id);
        plan.setTenantId(existing.getTenantId());
        schedulePlanMapper.updateById(plan);
        return schedulePlanMapper.selectById(id);
    }

    @Override
    public void deleteSchedulePlan(String id) {
        schedulePlanMapper.deleteById(id);
    }

    @Override
    @Transactional
    public List<SchedulePlan> batchCreateSchedules(String tenantId, String userId, List<SchedulePlanCreateRequest> requests) {
        List<SchedulePlan> plans = new ArrayList<>();
        for (SchedulePlanCreateRequest request : requests) {
            SchedulePlan plan = createSchedulePlan(tenantId, userId, request);
            plans.add(plan);
        }
        return plans;
    }

    @Override
    public List<Map<String, Object>> getTimetable(String tenantId, LocalDate startDate, LocalDate endDate, String classId) {
        if (startDate == null) {
            startDate = LocalDate.now();
        }
        if (endDate == null) {
            endDate = startDate.plusMonths(1);
        }

        LambdaQueryWrapper<SchedulePlan> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SchedulePlan::getTenantId, tenantId);
        if (classId != null) {
            wrapper.eq(SchedulePlan::getClassId, classId);
        }
        wrapper.le(SchedulePlan::getStartDate, endDate)
               .ge(SchedulePlan::getEndDate, startDate);

        List<SchedulePlan> plans = schedulePlanMapper.selectList(wrapper);

        // 按日期分组
        Map<String, List<Map<String, Object>>> dailySchedules = new LinkedHashMap<>();

        for (SchedulePlan plan : plans) {
            LocalDate date = plan.getStartDate();
            while (!date.isAfter(plan.getEndDate()) && !date.isAfter(endDate)) {
                String dateKey = date.toString();

                if (!dailySchedules.containsKey(dateKey)) {
                    dailySchedules.put(dateKey, new ArrayList<>());
                }

                Map<String, Object> schedule = new HashMap<>();
                schedule.put("id", plan.getId());
                schedule.put("date", dateKey);
                schedule.put("dayOfWeek", date.getDayOfWeek().getValue());
                schedule.put("classId", plan.getClassId());
                schedule.put("courseId", plan.getCourseId());
                schedule.put("teacherId", plan.getTeacherId());
                schedule.put("period", plan.getPeriod());
                schedule.put("startTime", plan.getStartTime());
                schedule.put("endTime", plan.getEndTime());
                schedule.put("location", plan.getLocation());

                dailySchedules.get(dateKey).add(schedule);

                date = date.plusDays(1);
            }
        }

        // 转换为前端需要的格式
        List<Map<String, Object>> result = new ArrayList<>();
        for (Map.Entry<String, List<Map<String, Object>>> entry : dailySchedules.entrySet()) {
            Map<String, Object> dayData = new HashMap<>();
            dayData.put("date", entry.getKey());
            dayData.put("schedules", entry.getValue());
            result.add(dayData);
        }

        return result;
    }

    @Override
    public Page<ScheduleTemplate> getScheduleTemplates(int pageNum, int pageSize, String tenantId) {
        Page<ScheduleTemplate> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<ScheduleTemplate> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ScheduleTemplate::getTenantId, tenantId)
               .orderByDesc(ScheduleTemplate::getCreatedAt);
        return scheduleTemplateMapper.selectPage(page, wrapper);
    }

    @Override
    public ScheduleTemplate getScheduleTemplateById(String id) {
        ScheduleTemplate template = scheduleTemplateMapper.selectById(id);
        if (template == null) {
            throw new BusinessException(ErrorCode.DATA_NOT_FOUND, "Schedule template not found");
        }
        return template;
    }

    @Override
    public ScheduleTemplate createScheduleTemplate(String tenantId, ScheduleTemplate template) {
        template.setTenantId(tenantId);
        scheduleTemplateMapper.insert(template);
        return template;
    }

    @Override
    public ScheduleTemplate updateScheduleTemplate(String id, ScheduleTemplate template) {
        ScheduleTemplate existing = getScheduleTemplateById(id);
        template.setId(id);
        template.setTenantId(existing.getTenantId());
        scheduleTemplateMapper.updateById(template);
        return scheduleTemplateMapper.selectById(id);
    }

    @Override
    public void deleteScheduleTemplate(String id) {
        scheduleTemplateMapper.deleteById(id);
    }

    @Override
    @Transactional
    public List<SchedulePlan> applyScheduleTemplate(String tenantId, String templateId, ScheduleTemplateApplyRequest request) {
        ScheduleTemplate template = getScheduleTemplateById(templateId);

        // 解析模板内容（JSON 格式）
        // 模板内容格式示例：[{"dayOfWeek": 1, "period": 1, "courseId": 1, "teacherId": 1, ...}]
        List<SchedulePlan> plans = new ArrayList<>();

        // TODO: 解析模板内容并创建课表计划
        // 这里需要根据实际的模板内容格式进行解析

        return plans;
    }
}
