"""Opening hours as observations: one row per reading, collected or entered by hand, nothing deleted.

An airport's duty free hours are a new source class (rian, 11 Sep 2026): read from the airport
operator's own site where its robots allow, typed in where they do not. Both arrive as the same
row, so the page never cares which it got; `source_kind` and the date are the provenance the page
shows. The newest row per airport and kind is the current one, and a hand row outranks a
collected one (`services/hours/store.py`): a human value is never overwritten by a machine, so a
later collected reading is stored beside it and not shown.

`location_id` points at one of the airport's shop rows (the first by id; an airport with two shops
still has one set of hours), which is how every other airport fact is keyed. `entered_by_id` is
the who-column of the build plan (§2): `FK accounts.id NULL`.
"""

from datetime import datetime

from sqlalchemy import JSON, DateTime, ForeignKey, String, Text, func
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.models.base import Base
from app.models.catalog import Account, Location

SOURCE_KINDS = ("collected", "hand")


class AirportHours(Base):
    __tablename__ = "airport_hours"

    id: Mapped[int] = mapped_column(primary_key=True)
    location_id: Mapped[int] = mapped_column(ForeignKey("locations.id"), nullable=False, index=True)
    #: "collected" (an operator page, `source_url` names it) or "hand" (`entered_by_id` names who).
    source_kind: Mapped[str] = mapped_column(String(12), nullable=False)
    entered_by_id: Mapped[int | None] = mapped_column(ForeignKey("accounts.id"))
    #: When the hours were read or typed. The page prints this date, never a rate.
    observed_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
    source_url: Mapped[str | None] = mapped_column(String(600))
    #: The one line the page shows under "Opening hours".
    text: Mapped[str] = mapped_column(Text, nullable=False)
    #: The reading behind the line: the stores, their terminals and times, the pages read.
    #: Portable JSON so the store tests run on SQLite; JSONB on Postgres.
    detail: Mapped[dict | None] = mapped_column(JSON().with_variant(JSONB(), "postgresql"))
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), server_default=func.now(), nullable=False
    )

    location: Mapped[Location] = relationship()
    entered_by: Mapped[Account | None] = relationship()
