import dataclasses
import enum

from mariner.models import html, json, url


class ResponseType(enum.Enum):
    """Response format returned by a tracker's search endpoint."""

    HTML = "html"
    JSON = "json"


@dataclasses.dataclass(frozen=True)
class Metadata:
    """Metadata for a tracker."""

    id: str
    name: str
    description: str


@dataclasses.dataclass(frozen=True)
class SearchPath:
    """Search path definition for a tracker."""

    path: url.Pathname
    inputs: dict[str, str] = dataclasses.field(default_factory=dict)
    response_type: ResponseType = ResponseType.HTML


@dataclasses.dataclass(frozen=True)
class DownloadSelector:
    """A single CSS selector for extracting a download link from a details page."""

    selector: str
    attribute: str = "href"


@dataclasses.dataclass(frozen=True)
class DownloadSpec:
    """Specification for resolving download links from a tracker's details page.

    When present, indicates that search results contain details page URLs
    rather than direct download/magnet links. Each selector is tried in
    order until one matches.
    """

    selectors: list[DownloadSelector]


@dataclasses.dataclass(frozen=True)
class SearchSpec:
    """Search specification for a tracker."""

    links: list[url.Site]
    paths: list[SearchPath]
    rows_selector: str
    fields: html.SearchFields | json.SearchFields
    rows_after: int = 0
    request_delay: float = 0
    config: dict[str, str] = dataclasses.field(default_factory=dict)
    download: DownloadSpec | None = None


@dataclasses.dataclass(frozen=True)
class Definition:
    """Tracker definition loaded from Jackett definition files."""

    metadata: Metadata
    spec: SearchSpec

    @property
    def description(self) -> str:
        """Return the tracker description."""
        return self.metadata.description

    @property
    def id(self) -> str:
        """Return the tracker ID."""
        return self.metadata.id

    @property
    def name(self) -> str:
        """Return the tracker name."""
        return self.metadata.name
