"""LAPIS intermediate model dataclasses.

These represent the structured LAPIS document before it is emitted as text.
"""

from __future__ import annotations

from dataclasses import dataclass, field


@dataclass
class LapisMeta:
    """The [meta] section."""

    api: str
    base: str
    version: str | None = None
    desc: str | None = None
    auth: str | None = None
    format: str | None = None


@dataclass
class LapisField:
    """A single field in a type definition, operation, webhook, or error."""

    name: str
    type_expr: str
    optional: bool = False
    default: str | None = None
    since: str | None = None
    deprecated: bool = False
    deprecated_note: str | None = None
    location: str | None = None
    header_name: str | None = None


@dataclass
class LapisEnumType:
    """An enum type: ``Name: val1 | val2 | val3``."""

    name: str
    values: list[str]


@dataclass
class LapisObjectType:
    """An object type with named fields."""

    name: str
    fields: list[LapisField]


@dataclass
class LapisOperation:
    """A single API operation in the [ops] section."""

    name: str
    method: str
    path: str
    description: str | None = None
    inputs: list[LapisField] = field(default_factory=list)
    outputs: list[LapisField] = field(default_factory=list)
    output_ref: str | None = None
    modifiers: list[str] = field(default_factory=list)
    since: str | None = None


@dataclass
class LapisWebhook:
    """A webhook event in the [webhooks] section."""

    name: str
    method: str
    path: str
    description: str | None = None
    triggers: list[str] = field(default_factory=list)
    outputs: list[LapisField] = field(default_factory=list)


@dataclass
class LapisError:
    """An error definition in the [errors] section."""

    code: int
    name: str
    description: str | None = None
    ops: list[str] = field(default_factory=list)
    fields: list[LapisField] = field(default_factory=list)


@dataclass
class LapisRateLimit:
    """A rate limit directive."""

    count: int
    window: str
    scope: str | None = None


@dataclass
class LapisQuota:
    """A quota directive."""

    count: int | None = None
    period: str | None = None
    unlimited: bool = False
    scope: str | None = None
    description: str | None = None


@dataclass
class LapisPlan:
    """A plan/tier block in [limits]."""

    name: str
    rates: list[LapisRateLimit] = field(default_factory=list)
    quotas: list[LapisQuota] = field(default_factory=list)
    max_batch: int | None = None


@dataclass
class LapisLimits:
    """The [limits] section."""

    headers: str | None = None
    on_exceed: str | None = None
    max_body: str | None = None
    max_upload: str | None = None
    max_response: str | None = None
    max_batch: int | None = None
    plans: list[LapisPlan] = field(default_factory=list)
    rates: list[LapisRateLimit] = field(default_factory=list)
    quotas: list[LapisQuota] = field(default_factory=list)


@dataclass
class LapisFlowCondition:
    """A condition in a flow (``? op: description``)."""

    op: str
    description: str


@dataclass
class LapisFlow:
    """A flow definition in the [flows] section."""

    name: str
    description: str
    chain: str
    conditions: list[LapisFlowCondition] = field(default_factory=list)
    narrative: str | None = None


@dataclass
class LapisDocument:
    """A complete LAPIS document."""

    meta: LapisMeta
    types: list[LapisEnumType | LapisObjectType] = field(default_factory=list)
    ops: list[LapisOperation] = field(default_factory=list)
    webhooks: list[LapisWebhook] = field(default_factory=list)
    errors: list[LapisError] = field(default_factory=list)
    error_base_type: str | None = None
    limits: LapisLimits | None = None
    flows: list[LapisFlow] = field(default_factory=list)
