import json
from dataclasses import dataclass
from datetime import date, datetime
from typing import Optional
from urllib.parse import urlencode
from urllib.request import Request, urlopen


_API_BASE = "https://api.aladhan.com/v1"


@dataclass(frozen=True)
class HijriDate:
    day: int
    month_number: int
    month_en: str
    month_ar: str
    year: int
    weekday_en: str
    weekday_ar: str

    def formatted(self) -> str:
        return f"{self.day} {self.month_ar} {self.year} هـ"


class HijriDateError(RuntimeError):
    pass


def _format_gregorian(d: date) -> str:
    # Aladhan expects DD-MM-YYYY
    return d.strftime("%d-%m-%Y")


def get_hijri_date(gregorian: date | str, *, adjustment: int = 0, user_agent: Optional[str] = None) -> HijriDate:
    """
    Convert Gregorian date to Hijri date using Aladhan API.

    adjustment:
        -1, 0, +1 ... (days) to adjust to local moon sighting.
    """
    if isinstance(gregorian, str):
        g = datetime.strptime(gregorian, "%Y-%m-%d").date()
    else:
        g = gregorian

    params = {"date": _format_gregorian(g)}
    if adjustment:
        params["adjustment"] = str(int(adjustment))

    url = f"{_API_BASE}/gToH?{urlencode(params)}"
    headers = {}
    if user_agent:
        headers["User-Agent"] = user_agent

    req = Request(url, headers=headers)
    with urlopen(req, timeout=10) as resp:
        payload = json.loads(resp.read().decode("utf-8"))

    if payload.get("code") != 200 or "data" not in payload:
        raise HijriDateError("Failed to convert date via Aladhan API.")

    hijri = payload["data"]["hijri"]
    return HijriDate(
        day=int(hijri["day"]),
        month_number=int(hijri["month"]["number"]),
        month_en=hijri["month"]["en"],
        month_ar=hijri["month"].get("ar", hijri["month"]["en"]),
        year=int(hijri["year"]),
        weekday_en=hijri["weekday"]["en"],
        weekday_ar=hijri["weekday"].get("ar", hijri["weekday"]["en"]),
    )
