<?php
namespace App\Services;

use DateTime;
use DateInterval;
use DatePeriod;

/**
 * Servicio para cálculos de fechas y semanas
 * Regla de negocio: Las semanas inician Domingo y terminan Sábado
 */
class WeekService
{
    /**
     * Obtiene la fecha de inicio (domingo) y fin (sábado) de la semana actual
     */
    public function getCurrentWeekDates()
    {
        $today = new DateTime();
        $dayOfWeek = $today->format('w'); // 0 (dom) a 6 (sab)
        
        // Calcular inicio (domingo de esta semana)
        $start = clone $today;
        $start->sub(new DateInterval("P{$dayOfWeek}D"));
        
        // Calcular fin (sábado de esta semana)
        $end = clone $start;
        $end->add(new DateInterval('P6D'));
        
        return [
            'start' => $start->format('Y-m-d'),
            'end' => $end->format('Y-m-d'),
            'week_number' => $start->format('W'), // Nota: 'W' usa estándar ISO (Lunes inicio), puede variar
            'year' => $start->format('Y')
        ];
    }
    
    /**
     * Obtiene el número de semana ajustado para inicio en domingo
     */
    public function getWeekNumber($dateStr)
    {
        $date = new DateTime($dateStr);
        // Si es domingo, PHP lo cuenta como final de la semana anterior en ISO-8601
        // Para nuestro caso, domingo es inicio, así que usamos el número de semana "natural"
        return (int)$date->format('W');
    }
    
    /**
     * Obtiene las fechas de una semana específica dado año y número
     */
    public function getWeekDates($year, $weekNumber)
    {
        $dto = new DateTime();
        // 'W' es ISO-8601, inicia Lunes. 
        // setISODate($year, $weekNumber, $day) -> 1=Lunes, 7=Domingo
        
        // Aproximación: obtener el lunes de esa semana ISO y restar 1 día para obtener el domingo previo
        $dto->setISODate($year, $weekNumber, 1); 
        $dto->sub(new DateInterval('P1D')); // Retroceder al Domingo
        
        $start = $dto;
        $end = clone $start;
        $end->add(new DateInterval('P6D')); // Sábado
        
        return [
            'start' => $start->format('Y-m-d'),
            'end' => $end->format('Y-m-d')
        ];
    }
    
    /**
     * Obtiene la fecha del próximo domingo (inicio de siguiente semana) dada una fecha de referencia
     */
    public function getNextWeekStart($dateStr)
    {
        $date = new DateTime($dateStr);
        $dayOfWeek = $date->format('w');
        
        // Ir al domingo de la semana actual de esa fecha
        $date->sub(new DateInterval("P{$dayOfWeek}D"));
        
        // Sumar 7 días
        $date->add(new DateInterval('P7D'));
        
        return $date->format('Y-m-d');
    }
    /**
     * Obtiene el número de semana actual
     */
    public function getCurrentWeekNumber()
    {
        $dates = $this->getCurrentWeekDates();
        return $dates['week_number'];
    }

    /**
     * Obtiene el año actual
     */
    public function getCurrentYear()
    {
        $dates = $this->getCurrentWeekDates();
        return $dates['year'];
    }

    /**
     * Alias para getWeekDates
     */
    public function getWeekDateRange($year, $weekNumber)
    {
        return $this->getWeekDates($year, $weekNumber);
    }
}
