package org.springblade.modules.martial.service.schedule.generator;

import lombok.extern.slf4j.Slf4j;
import org.springblade.modules.martial.pojo.entity.MartialCompetition;
import org.springblade.modules.martial.service.schedule.model.TimeSlot;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;

/**
 * Time slot generator for schedule arrangement
 * Generates available time slots based on competition dates
 * 
 * @author Refactored from MartialScheduleArrangeServiceImpl
 */
@Slf4j
@Component
public class TimeSlotGenerator {

    // Default time slot configurations
    private static final String MORNING_START = "08:00";
    private static final String AFTERNOON_START = "14:00";
    private static final String EVENING_START = "19:00";
    
    private static final int MORNING_CAPACITY = 240;    // 4 hours = 240 minutes
    private static final int AFTERNOON_CAPACITY = 240;  // 4 hours = 240 minutes
    private static final int EVENING_CAPACITY = 180;    // 3 hours = 180 minutes

    /**
     * Generate time slots for a competition
     * 
     * @param competition the competition entity
     * @return list of time slots
     */
    public List<TimeSlot> generate(MartialCompetition competition) {
        if (competition == null) {
            log.warn("Competition is null, returning empty time slots");
            return new ArrayList<>();
        }
        return generate(
            competition.getCompetitionStartTime(),
            competition.getCompetitionEndTime()
        );
    }

    /**
     * Generate time slots between start and end time
     * 
     * @param startTime competition start time
     * @param endTime competition end time
     * @return list of time slots
     */
    public List<TimeSlot> generate(LocalDateTime startTime, LocalDateTime endTime) {
        List<TimeSlot> timeSlots = new ArrayList<>();

        if (startTime == null || endTime == null) {
            log.warn("Competition time info incomplete, returning empty time slots");
            return timeSlots;
        }

        LocalDate currentDate = startTime.toLocalDate();
        LocalDate endDate = endTime.toLocalDate();

        while (!currentDate.isAfter(endDate)) {
            timeSlots.addAll(generateDailySlots(currentDate));
            currentDate = currentDate.plusDays(1);
        }

        long days = ChronoUnit.DAYS.between(startTime.toLocalDate(), endDate) + 1;
        log.info("Generated time slots: {} days, 3 slots per day (morning/afternoon/evening), total {} slots",
            days, timeSlots.size());

        return timeSlots;
    }

    /**
     * Generate time slots for a single day
     * 
     * @param date the date
     * @return list of time slots for that day
     */
    public List<TimeSlot> generateDailySlots(LocalDate date) {
        List<TimeSlot> slots = new ArrayList<>();

        // Morning slot (08:00-12:00)
        slots.add(TimeSlot.builder()
            .date(date)
            .period("morning")
            .startTime(MORNING_START)
            .capacity(MORNING_CAPACITY)
            .build());

        // Afternoon slot (14:00-18:00)
        slots.add(TimeSlot.builder()
            .date(date)
            .period("afternoon")
            .startTime(AFTERNOON_START)
            .capacity(AFTERNOON_CAPACITY)
            .build());

        // Evening slot (19:00-22:00)
        slots.add(TimeSlot.builder()
            .date(date)
            .period("evening")
            .startTime(EVENING_START)
            .capacity(EVENING_CAPACITY)
            .build());

        return slots;
    }

    /**
     * Calculate total capacity in minutes
     * 
     * @param timeSlots list of time slots
     * @return total capacity in minutes
     */
    public int calculateTotalCapacity(List<TimeSlot> timeSlots) {
        return timeSlots.stream()
            .mapToInt(TimeSlot::getCapacity)
            .sum();
    }
}
