package com.lesingle.edu.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.lesingle.edu.common.enums.GenericStatus;
import com.lesingle.edu.common.enums.ScheduleSourceType;
import com.lesingle.edu.common.enums.ErrorCode;
import com.lesingle.edu.common.exception.BusinessException;
import com.lesingle.edu.dto.request.SchedulePlanCreateRequest;
import com.lesingle.edu.dto.request.SchedulePlanUpdateRequest;
import com.lesingle.edu.dto.response.SchedulePlanResponse;
import com.lesingle.edu.dto.response.TimetableResponse;
import com.lesingle.edu.entity.SchedulePlan;
import com.lesingle.edu.mapper.SchedulePlanMapper;
import com.lesingle.edu.service.SchoolScheduleService;
import com.lesingle.edu.service.TeacherScheduleService;
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.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 教师端排课服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class TeacherScheduleServiceImpl extends ServiceImpl<SchedulePlanMapper, SchedulePlan>
    implements TeacherScheduleService {

    private final SchedulePlanMapper schedulePlanMapper;
    private final SchoolScheduleService schoolScheduleService;

    @Override
    public Page<SchedulePlan> getTeacherSchedules(Long teacherId, Integer pageNum, Integer pageSize,
                                                   LocalDate startDate, LocalDate endDate) {
        Page<SchedulePlan> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<SchedulePlan> wrapper = new LambdaQueryWrapper<>();

        wrapper.eq(SchedulePlan::getTeacherId, teacherId);

        if (startDate != null) {
            wrapper.ge(SchedulePlan::getScheduledDate, startDate);
        }
        if (endDate != null) {
            wrapper.le(SchedulePlan::getScheduledDate, endDate);
        }

        wrapper.orderByAsc(SchedulePlan::getScheduledDate);

        return schedulePlanMapper.selectPage(page, wrapper);
    }

    @Override
    public List<TimetableResponse> getTimetable(Long teacherId, LocalDate startDate, LocalDate endDate) {
        LambdaQueryWrapper<SchedulePlan> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SchedulePlan::getTeacherId, teacherId);
        wrapper.eq(SchedulePlan::getStatus, GenericStatus.ACTIVE.getCode());

        if (startDate != null) {
            wrapper.ge(SchedulePlan::getScheduledDate, startDate);
        }
        if (endDate != null) {
            wrapper.le(SchedulePlan::getScheduledDate, endDate);
        }

        wrapper.orderByAsc(SchedulePlan::getScheduledDate);

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

        // 按日期分组，使用 schoolScheduleService.toSchedulePlanResponse 填充 className、courseName 等展示字段
        return schedules.stream()
            .collect(Collectors.groupingBy(SchedulePlan::getScheduledDate))
            .entrySet().stream()
            .map(entry -> {
                LocalDate date = entry.getKey();
                List<SchedulePlan> daySchedules = entry.getValue();
                return TimetableResponse.builder()
                    .date(date)
                    .weekDay(date != null ? date.getDayOfWeek().getValue() : null)
                    .schedules(daySchedules.stream()
                        .map(schoolScheduleService::toSchedulePlanResponse)
                        .collect(Collectors.toList()))
                    .build();
            })
            .collect(Collectors.toList());
    }

    @Override
    public List<SchedulePlan> getTodaySchedules(Long teacherId) {
        LocalDate today = LocalDate.now();
        LambdaQueryWrapper<SchedulePlan> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SchedulePlan::getTeacherId, teacherId);
        wrapper.eq(SchedulePlan::getScheduledDate, today);
        wrapper.eq(SchedulePlan::getStatus, GenericStatus.ACTIVE.getCode());
        wrapper.orderByAsc(SchedulePlan::getScheduledTime);

        return schedulePlanMapper.selectList(wrapper);
    }

    @Override
    public SchedulePlan getScheduleById(Long scheduleId) {
        SchedulePlan schedulePlan = schedulePlanMapper.selectById(scheduleId);
        if (schedulePlan == null) {
            throw new BusinessException(ErrorCode.DATA_NOT_FOUND, "排课计划不存在");
        }
        return schedulePlan;
    }

    @Override
    @Transactional
    public SchedulePlan createSchedule(Long tenantId, Long teacherId, SchedulePlanCreateRequest request) {
        SchedulePlan schedulePlan = new SchedulePlan();
        schedulePlan.setTenantId(tenantId);
        schedulePlan.setName(request.getName());
        schedulePlan.setClassId(request.getClassId());
        schedulePlan.setCourseId(request.getCourseId());
        schedulePlan.setCoursePackageId(request.getCoursePackageId());
        schedulePlan.setLessonType(request.getLessonType());
        schedulePlan.setTeacherId(request.getTeacherId() != null ? request.getTeacherId() : teacherId);
        schedulePlan.setScheduledDate(request.getScheduledDate());
        schedulePlan.setScheduledTime(request.getScheduledTime());
        schedulePlan.setWeekDay(request.getWeekDay());
        schedulePlan.setRepeatType(request.getRepeatType() != null ? request.getRepeatType() : "NONE");
        schedulePlan.setRepeatEndDate(request.getRepeatEndDate());
        schedulePlan.setSource(request.getSource() != null ? request.getSource() : ScheduleSourceType.TEACHER.getCode());
        schedulePlan.setNote(request.getNote());
        schedulePlan.setStatus(GenericStatus.ACTIVE.getCode());

        schedulePlanMapper.insert(schedulePlan);
        log.info("排课创建成功：id={}, name={}, scheduledDate={}",
            schedulePlan.getId(), schedulePlan.getName(), schedulePlan.getScheduledDate());
        return schedulePlan;
    }

    @Override
    @Transactional
    public SchedulePlan updateSchedule(Long scheduleId, SchedulePlanUpdateRequest request) {
        SchedulePlan schedulePlan = getScheduleById(scheduleId);

        if (StringUtils.hasText(request.getName())) {
            schedulePlan.setName(request.getName());
        }
        if (request.getCourseId() != null) {
            schedulePlan.setCourseId(request.getCourseId());
        }
        if (request.getTeacherId() != null) {
            schedulePlan.setTeacherId(request.getTeacherId());
        }
        if (request.getScheduledDate() != null) {
            schedulePlan.setScheduledDate(request.getScheduledDate());
        }
        if (StringUtils.hasText(request.getScheduledTime())) {
            schedulePlan.setScheduledTime(request.getScheduledTime());
        }
        if (request.getWeekDay() != null) {
            schedulePlan.setWeekDay(request.getWeekDay());
        }
        if (StringUtils.hasText(request.getRepeatType())) {
            schedulePlan.setRepeatType(request.getRepeatType());
        }
        if (request.getRepeatEndDate() != null) {
            schedulePlan.setRepeatEndDate(request.getRepeatEndDate());
        }
        if (StringUtils.hasText(request.getStatus())) {
            schedulePlan.setStatus(request.getStatus());
        }
        if (request.getNote() != null) {
            schedulePlan.setNote(request.getNote());
        }

        schedulePlanMapper.updateById(schedulePlan);
        log.info("排课更新成功：id={}", scheduleId);
        return schedulePlan;
    }

    @Override
    @Transactional
    public void cancelSchedule(Long scheduleId) {
        SchedulePlan schedulePlan = getScheduleById(scheduleId);
        schedulePlan.setStatus("CANCELLED");
        schedulePlanMapper.updateById(schedulePlan);
        log.info("排课取消成功：id={}", scheduleId);
    }
}
