"""
Hardcoded event logic for Vietnam holidays and seasons.
"""

from __future__ import annotations

import re
from dataclasses import dataclass
from datetime import date, datetime
from typing import Optional


@dataclass(frozen=True)
class EventDef:
    name: str
    month: int
    day: int
    tags: list[str]
    keywords: list[str]
    master_color: Optional[str] = None
    product_line_vn: Optional[list[str]] = None


_EVENTS: list[EventDef] = [
    EventDef(
        name="Ngày Giải phóng miền Nam (30/4)",
        month=4,
        day=30,
        tags=["Màu đỏ", "Đi chơi / dạo phố"],
        keywords=["cờ đỏ sao vàng", "lễ hội", "đi chơi"],
        master_color="Màu đỏ",
        product_line_vn=["Áo phông", "Quần jean", "Váy liền"],
    ),
    EventDef(
        name="Quốc khánh (2/9)",
        month=9,
        day=2,
        tags=["Màu đỏ", "Đi chơi / dạo phố"],
        keywords=["cờ đỏ sao vàng", "quốc khánh", "lễ hội"],
        master_color="Màu đỏ",
        product_line_vn=["Áo phông", "Quần jean", "Váy liền"],
    ),
    EventDef(
        name="Tết Nguyên Đán",
        month=1,
        day=1,
        tags=["Màu đỏ", "Đi chơi / dạo phố"],
        keywords=["Tết", "du xuân", "may mắn"],
        master_color="Màu đỏ",
        product_line_vn=["Váy liền", "Chân váy", "Áo kiểu", "Áo sơ mi", "Quần Khaki", "Áo dài"],
    ),
    EventDef(
        name="Ngày Quốc tế Phụ nữ (8/3)",
        month=3,
        day=8,
        tags=["Đi chơi / dạo phố", "Đi tiệc"],
        keywords=["thanh lịch", "duyên dáng", "nữ tính"],
        product_line_vn=["Váy liền", "Chân váy", "Áo kiểu", "Blazer"],
    ),
    EventDef(
        name="Ngày Phụ nữ Việt Nam (20/10)",
        month=10,
        day=20,
        tags=["Đi chơi / dạo phố", "Đi tiệc"],
        keywords=["thanh lịch", "sang trọng", "duyên dáng"],
        product_line_vn=["Váy liền", "Chân váy", "Áo kiểu", "Blazer"],
    ),
    EventDef(
        name="Valentine (14/2)",
        month=2,
        day=14,
        tags=["Màu hồng", "Đi tiệc"],
        keywords=["Valentine", "lãng mạn", "duyên dáng"],
        master_color="Màu hồng",
        product_line_vn=["Váy liền", "Áo kiểu", "Chân váy"],
    ),
    EventDef(
        name="Giáng sinh (25/12)",
        month=12,
        day=25,
        tags=["Màu đỏ", "Đi tiệc"],
        keywords=["giáng sinh", "nổi bật", "vui vẻ"],
        master_color="Màu đỏ",
        product_line_vn=["Váy liền", "Áo kiểu", "Blazer"],
    ),
]


_KEYWORD_EVENT_MAP: dict[str, str] = {
    "30/4": "Ngày Giải phóng miền Nam (30/4)",
    "2/9": "Quốc khánh (2/9)",
    "quốc khánh": "Quốc khánh (2/9)",
    "tet": "Tết Nguyên Đán",
    "tết": "Tết Nguyên Đán",
    "valentine": "Valentine (14/2)",
    "giáng sinh": "Giáng sinh (25/12)",
    "noel": "Giáng sinh (25/12)",
    "20/10": "Ngày Phụ nữ Việt Nam (20/10)",
    "8/3": "Ngày Quốc tế Phụ nữ (8/3)",
}


def _get_season(d: date) -> str:
    month = d.month
    if month in (12, 1, 2):
        return "Mùa đông"
    if month in (3, 4, 5):
        return "Mùa xuân"
    if month in (6, 7, 8):
        return "Mùa hè"
    return "Mùa thu"


def _find_event_by_name(name: str) -> Optional[EventDef]:
    for ev in _EVENTS:
        if ev.name == name:
            return ev
    return None


def _find_event_by_date(month: int, day: int) -> Optional[EventDef]:
    for ev in _EVENTS:
        if ev.month == month and ev.day == day:
            return ev
    return None


def _find_event_in_query(query: str) -> Optional[EventDef]:
    if not query:
        return None

    query_lower = query.lower()

    # Match explicit date like 30/4, 2-9, 2.9
    date_match = re.search(r"\b(\d{1,2})[\./-](\d{1,2})\b", query_lower)
    if date_match:
        day = int(date_match.group(1))
        month = int(date_match.group(2))
        ev = _find_event_by_date(month, day)
        if ev:
            return ev

    for key, name in _KEYWORD_EVENT_MAP.items():
        if key in query_lower:
            return _find_event_by_name(name)

    return None


def _next_event(today: date) -> Optional[EventDef]:
    for ev in sorted(_EVENTS, key=lambda x: (x.month, x.day)):
        if (ev.month, ev.day) >= (today.month, today.day):
            return ev
    return _EVENTS[0] if _EVENTS else None


def get_event_context(query: str | None, today: date | None = None) -> dict:
    now = today or datetime.now().date()
    season = _get_season(now)

    mentioned = _find_event_in_query(query or "")
    current = _find_event_by_date(now.month, now.day)
    upcoming = _next_event(now)

    def _event_to_dict(ev: EventDef | None) -> Optional[dict]:
        if not ev:
            return None
        return {
            "name": ev.name,
            "date": f"{ev.day:02d}/{ev.month:02d}",
            "tags": ev.tags,
            "keywords": ev.keywords,
            "master_color": ev.master_color,
            "product_line_vn": ev.product_line_vn or [],
        }

    return {
        "today": now.strftime("%d/%m/%Y"),
        "season": season,
        "mentioned_event": _event_to_dict(mentioned),
        "current_event": _event_to_dict(current),
        "next_event": _event_to_dict(upcoming),
    }
