<?php
namespace App\Services;

use App\Models\User;
use App\Models\Assignment;
use DateTime;
use DateInterval;

/**
 * Servicio para la generación automática de rotaciones
 */
class RotationService
{
    private $userModel;
    private $assignmentModel;
    private $weekService;
    
    public function __construct()
    {
        $this->userModel = new User();
        $this->assignmentModel = new Assignment();
        $this->weekService = new WeekService();
    }
    
    /**
     * Genera las próximas N semanas de rotación
     * 
     * @param int $weeksCount Número de semanas a generar
     * @return int Número de asignaciones creadas
     */
    public function generateNext($weeksCount = 8)
    {
        // 1. Obtener todos los ayudantes y coordinadores activos ordenados
        // El orden es crucial para la rotación constante
        $helpers = $this->userModel->getAllHelpers();
        
        if (empty($helpers)) {
            return 0;
        }
        
        // 2. Obtener la última asignación registrada para saber dónde continuar
        $lastAssignment = $this->assignmentModel->getLatest();
        
        $nextDate = null;
        $nextHelperIndex = 0;
        
        if ($lastAssignment) {
            // Continuar desde la siguiente semana de la última asignación
            $nextDate = $this->weekService->getNextWeekStart($lastAssignment['start_date']);
            
            // Buscar índice del último usuario asignado para continuar con el siguiente
            $lastUserId = $lastAssignment['user_id'];
            foreach ($helpers as $index => $helper) {
                if ($helper['id'] == $lastUserId) {
                    $nextHelperIndex = ($index + 1) % count($helpers);
                    break;
                }
            }
        } else {
            // Si no hay asignaciones previas, empezar desde la semana actual
            $dates = $this->weekService->getCurrentWeekDates();
            $nextDate = $dates['start'];
            
            // Empezar con el primer ayudante de la lista (orden alfabético por defecto en User::getAllHelpers)
            $nextHelperIndex = 0;
        }
        
        $count = 0;
        
        // 3. Generar las asignaciones
        for ($i = 0; $i < $weeksCount; $i++) {
            // Calcular fecha fin (sábado)
            $startDateObj = new DateTime($nextDate);
            $endDateObj = clone $startDateObj;
            $endDateObj->add(new DateInterval('P6D'));
            
            $weekNumber = (int)$startDateObj->format('W');
            $year = (int)$startDateObj->format('Y');
            
            // Verificar si ya existe asignación para esta semana (evitar duplicados)
            if (!$this->assignmentModel->existsForWeek($year, $weekNumber)) {
                $helper = $helpers[$nextHelperIndex];
                
                $data = [
                    'user_id' => $helper['id'],
                    'week_number' => $weekNumber,
                    'year' => $year,
                    'start_date' => $startDateObj->format('Y-m-d'),
                    'end_date' => $endDateObj->format('Y-m-d'),
                    'order_position' => $count // Opcional, útil si se implementa reordenamiento futuro
                ];
                
                $this->assignmentModel->create($data);
                $count++;
            }
            
            // Avanzar al siguiente ayudante
            $nextHelperIndex = ($nextHelperIndex + 1) % count($helpers);
            
            // Avanzar a la siguiente semana
            $nextDateObj = new DateTime($nextDate);
            $nextDateObj->add(new DateInterval('P7D'));
            $nextDate = $nextDateObj->format('Y-m-d');
        }
        
        return $count;
    }
    
    /**
     * Regenera las asignaciones futuras basándose en el orden maestro de usuarios
     * Mantiene historial pasado, limpia futuro próximo y regenera.
     */
    public function regenerateFutureFromOrder()
    {
        // 1. Definir fecha de corte: HOY
        // No borramos asignaciones pasadas ni la actual en curso para no romper historial.
        $today = date('Y-m-d');
        
        // Pero debemos tener cuidado: Si estamos a mitad de semana, la asignación actual DEBE mantenerse.
        // La función deleteFutureAssignments borrará todo lo que empiece DESPUÉS de una fecha dada.
        // Vamos a calcular el fin de la semana actual.
        $currentWeek = $this->weekService->getCurrentWeekNumber();
        $currentYear = $this->weekService->getCurrentYear();
        $dates = $this->weekService->getWeekDateRange($currentYear, $currentWeek);
        
        $cutOffDate = $dates['end']; // Sábado de esta semana
        
        // Eliminar asignaciones que empiezan DESPUÉS de esta semana
        $this->assignmentModel->deleteFutureAssignments($cutOffDate);
        
        // 2. Generar nuevas asignaciones
        // Esto automáticamente buscará la última asignación válida (la de esta semana) 
        // y continuará desde la siguiente fecha con el siguiente usuario del ciclo maestro.
        return $this->generateNext(12); // Generar 12 semanas
    }
}
