# services/external/app/registry/calendar_registry.py
"""
Calendar Registry - Pre-configured school calendars and local events
"""

from dataclasses import dataclass
from typing import List, Optional, Dict, Any
from datetime import date
from enum import Enum


class SchoolType(str, Enum):
    PRIMARY = "primary"
    SECONDARY = "secondary"
    UNIVERSITY = "university"


@dataclass
class HolidayPeriod:
    """School holiday period definition"""
    name: str
    start_date: str  # ISO format: "2024-12-20"
    end_date: str    # ISO format: "2025-01-08"
    description: Optional[str] = None


@dataclass
class SchoolHours:
    """School operating hours configuration"""
    morning_start: str           # "09:00"
    morning_end: str             # "14:00"
    has_afternoon_session: bool  # True/False
    afternoon_start: Optional[str] = None  # "15:00" if has_afternoon_session
    afternoon_end: Optional[str] = None    # "17:00" if has_afternoon_session


@dataclass
class CalendarDefinition:
    """School calendar configuration for a specific city and school type"""
    calendar_id: str
    calendar_name: str
    city_id: str
    school_type: SchoolType
    academic_year: str  # "2024-2025"
    holiday_periods: List[HolidayPeriod]
    school_hours: SchoolHours
    source: str
    enabled: bool = True


class CalendarRegistry:
    """Central registry of school calendars for forecasting"""

    # Madrid Primary School Calendar 2024-2025 (Official Comunidad de Madrid - ORDEN 1177/2024)
    MADRID_PRIMARY_2024_2025 = CalendarDefinition(
        calendar_id="madrid_primary_2024_2025",
        calendar_name="Madrid Primary School Calendar 2024-2025",
        city_id="madrid",
        school_type=SchoolType.PRIMARY,
        academic_year="2024-2025",
        holiday_periods=[
            HolidayPeriod(
                name="Christmas Holiday",
                start_date="2024-12-21",
                end_date="2025-01-07",
                description="Official Christmas break - Comunidad de Madrid (Dec 21 - Jan 7)"
            ),
            HolidayPeriod(
                name="Easter Holiday (Semana Santa)",
                start_date="2025-04-11",
                end_date="2025-04-21",
                description="Official Easter break - Comunidad de Madrid (Apr 11-21)"
            ),
            HolidayPeriod(
                name="Summer Holiday",
                start_date="2025-06-21",
                end_date="2025-09-08",
                description="Summer vacation (Last day Jun 20, classes resume Sep 9)"
            ),
            HolidayPeriod(
                name="All Saints Long Weekend",
                start_date="2024-10-31",
                end_date="2024-11-03",
                description="October 31 - November 3 non-working days"
            ),
            HolidayPeriod(
                name="February Long Weekend",
                start_date="2025-02-28",
                end_date="2025-03-03",
                description="February 28 - March 3 non-working days"
            ),
        ],
        school_hours=SchoolHours(
            morning_start="09:00",
            morning_end="14:00",
            has_afternoon_session=False
        ),
        source="comunidad_madrid_orden_1177_2024",
        enabled=True
    )

    # Madrid Secondary School Calendar 2024-2025 (Official Comunidad de Madrid - ORDEN 1177/2024)
    MADRID_SECONDARY_2024_2025 = CalendarDefinition(
        calendar_id="madrid_secondary_2024_2025",
        calendar_name="Madrid Secondary School Calendar 2024-2025",
        city_id="madrid",
        school_type=SchoolType.SECONDARY,
        academic_year="2024-2025",
        holiday_periods=[
            HolidayPeriod(
                name="Christmas Holiday",
                start_date="2024-12-21",
                end_date="2025-01-07",
                description="Official Christmas break - Comunidad de Madrid (Dec 21 - Jan 7)"
            ),
            HolidayPeriod(
                name="Easter Holiday (Semana Santa)",
                start_date="2025-04-11",
                end_date="2025-04-21",
                description="Official Easter break - Comunidad de Madrid (Apr 11-21)"
            ),
            HolidayPeriod(
                name="Summer Holiday",
                start_date="2025-06-21",
                end_date="2025-09-09",
                description="Summer vacation (Last day Jun 20, classes resume Sep 10)"
            ),
            HolidayPeriod(
                name="All Saints Long Weekend",
                start_date="2024-10-31",
                end_date="2024-11-03",
                description="October 31 - November 3 non-working days"
            ),
            HolidayPeriod(
                name="February Long Weekend",
                start_date="2025-02-28",
                end_date="2025-03-03",
                description="February 28 - March 3 non-working days"
            ),
        ],
        school_hours=SchoolHours(
            morning_start="09:00",
            morning_end="14:00",
            has_afternoon_session=False
        ),
        source="comunidad_madrid_orden_1177_2024",
        enabled=True
    )

    # Madrid Primary School Calendar 2025-2026 (Official Comunidad de Madrid - ORDEN 1476/2025)
    MADRID_PRIMARY_2025_2026 = CalendarDefinition(
        calendar_id="madrid_primary_2025_2026",
        calendar_name="Madrid Primary School Calendar 2025-2026",
        city_id="madrid",
        school_type=SchoolType.PRIMARY,
        academic_year="2025-2026",
        holiday_periods=[
            HolidayPeriod(
                name="Christmas Holiday",
                start_date="2025-12-20",
                end_date="2026-01-07",
                description="Official Christmas break - Comunidad de Madrid (Dec 20 - Jan 7)"
            ),
            HolidayPeriod(
                name="Easter Holiday (Semana Santa)",
                start_date="2026-03-27",
                end_date="2026-04-06",
                description="Official Easter break - Comunidad de Madrid (Mar 27 - Apr 6)"
            ),
            HolidayPeriod(
                name="Summer Holiday",
                start_date="2026-06-21",
                end_date="2026-09-08",
                description="Summer vacation (classes resume Sep 9)"
            ),
            HolidayPeriod(
                name="October Long Weekend",
                start_date="2025-10-13",
                end_date="2025-10-13",
                description="October 13 non-working day (after Día de la Hispanidad)"
            ),
            HolidayPeriod(
                name="All Saints Long Weekend",
                start_date="2025-11-03",
                end_date="2025-11-03",
                description="November 3 non-working day (after All Saints)"
            ),
        ],
        school_hours=SchoolHours(
            morning_start="09:00",
            morning_end="14:00",
            has_afternoon_session=False
        ),
        source="comunidad_madrid_orden_1476_2025",
        enabled=True
    )

    # Madrid Secondary School Calendar 2025-2026 (Official Comunidad de Madrid - ORDEN 1476/2025)
    MADRID_SECONDARY_2025_2026 = CalendarDefinition(
        calendar_id="madrid_secondary_2025_2026",
        calendar_name="Madrid Secondary School Calendar 2025-2026",
        city_id="madrid",
        school_type=SchoolType.SECONDARY,
        academic_year="2025-2026",
        holiday_periods=[
            HolidayPeriod(
                name="Christmas Holiday",
                start_date="2025-12-20",
                end_date="2026-01-07",
                description="Official Christmas break - Comunidad de Madrid (Dec 20 - Jan 7)"
            ),
            HolidayPeriod(
                name="Easter Holiday (Semana Santa)",
                start_date="2026-03-27",
                end_date="2026-04-06",
                description="Official Easter break - Comunidad de Madrid (Mar 27 - Apr 6)"
            ),
            HolidayPeriod(
                name="Summer Holiday",
                start_date="2026-06-21",
                end_date="2026-09-09",
                description="Summer vacation (classes resume Sep 10)"
            ),
            HolidayPeriod(
                name="October Long Weekend",
                start_date="2025-10-13",
                end_date="2025-10-13",
                description="October 13 non-working day (after Día de la Hispanidad)"
            ),
            HolidayPeriod(
                name="All Saints Long Weekend",
                start_date="2025-11-03",
                end_date="2025-11-03",
                description="November 3 non-working day (after All Saints)"
            ),
        ],
        school_hours=SchoolHours(
            morning_start="09:00",
            morning_end="14:00",
            has_afternoon_session=False
        ),
        source="comunidad_madrid_orden_1476_2025",
        enabled=True
    )

    # Registry of all calendars
    CALENDARS: List[CalendarDefinition] = [
        MADRID_PRIMARY_2024_2025,
        MADRID_SECONDARY_2024_2025,
        MADRID_PRIMARY_2025_2026,
        MADRID_SECONDARY_2025_2026,
    ]

    @classmethod
    def get_all_calendars(cls) -> List[CalendarDefinition]:
        """Get all calendars"""
        return cls.CALENDARS

    @classmethod
    def get_enabled_calendars(cls) -> List[CalendarDefinition]:
        """Get all enabled calendars"""
        return [cal for cal in cls.CALENDARS if cal.enabled]

    @classmethod
    def get_calendar(cls, calendar_id: str) -> Optional[CalendarDefinition]:
        """Get calendar by ID"""
        for cal in cls.CALENDARS:
            if cal.calendar_id == calendar_id:
                return cal
        return None

    @classmethod
    def get_calendars_for_city(cls, city_id: str) -> List[CalendarDefinition]:
        """Get all enabled calendars for a specific city"""
        return [
            cal for cal in cls.CALENDARS
            if cal.city_id == city_id and cal.enabled
        ]

    @classmethod
    def get_calendar_for_city_and_type(
        cls,
        city_id: str,
        school_type: SchoolType,
        academic_year: Optional[str] = None
    ) -> Optional[CalendarDefinition]:
        """Get specific calendar for city, type, and optionally year"""
        for cal in cls.CALENDARS:
            if (cal.city_id == city_id and
                cal.school_type == school_type and
                cal.enabled and
                (academic_year is None or cal.academic_year == academic_year)):
                return cal
        return None

    @classmethod
    def to_dict(cls, calendar: CalendarDefinition) -> Dict[str, Any]:
        """Convert calendar definition to dictionary for JSON serialization"""
        return {
            "calendar_id": calendar.calendar_id,
            "calendar_name": calendar.calendar_name,
            "city_id": calendar.city_id,
            "school_type": calendar.school_type.value,
            "academic_year": calendar.academic_year,
            "holiday_periods": [
                {
                    "name": hp.name,
                    "start_date": hp.start_date,
                    "end_date": hp.end_date,
                    "description": hp.description
                }
                for hp in calendar.holiday_periods
            ],
            "school_hours": {
                "morning_start": calendar.school_hours.morning_start,
                "morning_end": calendar.school_hours.morning_end,
                "has_afternoon_session": calendar.school_hours.has_afternoon_session,
                "afternoon_start": calendar.school_hours.afternoon_start,
                "afternoon_end": calendar.school_hours.afternoon_end,
            },
            "source": calendar.source,
            "enabled": calendar.enabled
        }


# Local Events Registry for Madrid
@dataclass
class LocalEventDefinition:
    """Local event that impacts demand"""
    event_id: str
    name: str
    city_id: str
    date: str  # ISO format or "annual-MM-DD" for recurring
    impact_level: str  # "low", "medium", "high"
    description: Optional[str] = None
    recurring: bool = False  # True for annual events


class LocalEventsRegistry:
    """Registry of local events and festivals"""

    MADRID_EVENTS = [
        LocalEventDefinition(
            event_id="madrid_san_isidro",
            name="San Isidro Festival",
            city_id="madrid",
            date="annual-05-15",
            impact_level="high",
            description="Madrid's patron saint festival - major citywide celebration",
            recurring=True
        ),
        LocalEventDefinition(
            event_id="madrid_dos_de_mayo",
            name="Dos de Mayo",
            city_id="madrid",
            date="annual-05-02",
            impact_level="medium",
            description="Madrid regional holiday",
            recurring=True
        ),
        LocalEventDefinition(
            event_id="madrid_almudena",
            name="Virgen de la Almudena",
            city_id="madrid",
            date="annual-11-09",
            impact_level="medium",
            description="Madrid patron saint day",
            recurring=True
        ),
    ]

    @classmethod
    def get_events_for_city(cls, city_id: str) -> List[LocalEventDefinition]:
        """Get all local events for a city"""
        if city_id == "madrid":
            return cls.MADRID_EVENTS
        return []
