"""fddb.info source adapter.

Handles login, session cookies, and HTML page fetching.  Returns raw
HTML payloads wrapped in provenance envelopes.  No scraping or domain
logic — this module knows how to talk to fddb.info and nothing else.
"""

from datetime import datetime, timezone

from byteb4rb1e.homeostat.envelope import Envelope
from byteb4rb1e.homeostat.util.http import HttpSession

FDDB_BASE = "https://fddb.info"
LOGIN_URL = f"{FDDB_BASE}/db/i18n/account/"
NOTEPAD_URL = f"{FDDB_BASE}/db/i18n/notepad/"
USER_AGENT = (
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36"
)


class LoginFailed(Exception):
    """Raised when fddb.info login does not succeed."""


class FddbAdapter:
    """Low-level fddb.info client with session management."""

    def __init__(
        self, username: str, password: str
    ) -> None:
        self._username = username
        self._password = password
        self._logged_in = False
        self._session = HttpSession(
            default_headers={"User-Agent": USER_AGENT},
        )

    # -- Session -------------------------------------------------------------

    def login(self) -> None:
        """Log in to fddb.info and establish a session.

        Raises LoginFailed if the response does not indicate a
        successful login.
        """
        resp = self._session.post(
            f"{LOGIN_URL}?lang=en&action=login",
            data={
                "loginemailorusername": self._username,
                "loginpassword": self._password,
            },
        )

        body = resp.text.lower()
        if "logout" in body or "abmelden" in body:
            self._logged_in = True
        else:
            raise LoginFailed(
                "Login response did not contain logout indicator."
            )

    def _require_login(self) -> None:
        if not self._logged_in:
            raise RuntimeError(
                "Not logged in. Call login() first."
            )

    # -- Endpoint helpers ----------------------------------------------------

    def month_diary(self, month: int, year: int) -> Envelope:
        """Fetch the food diary page for an entire month.

        Returns an Envelope containing the raw HTML of the month
        diary page.
        """
        self._require_login()

        fetched_at = datetime.now(timezone.utc).isoformat()

        resp = self._session.get(
            NOTEPAD_URL,
            params={
                "lang": "en",
                "action": "npfe",
                "mode": "2",
                "month": str(month),
                "year": str(year),
            },
        )

        return Envelope(
            source="fddb",
            endpoint=f"notepad/month/{year}-{month:02d}",
            fetched_at=fetched_at,
            payload=resp.text,
        )

    def day_detail(self, detail_url: str) -> Envelope:
        """Fetch the detail page for a specific day.

        The detail_url comes from parsing the month diary page.
        It may be relative or absolute.

        Returns an Envelope containing the raw HTML of the detail
        page.
        """
        self._require_login()

        if not detail_url.startswith("http"):
            detail_url = (
                f"{FDDB_BASE}/{detail_url.lstrip('/')}"
            )

        fetched_at = datetime.now(timezone.utc).isoformat()
        resp = self._session.get(detail_url)

        return Envelope(
            source="fddb",
            endpoint=detail_url,
            fetched_at=fetched_at,
            payload=resp.text,
        )
