from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path
from typing import Any

from .render import structured_tail
from .source import SourcePackage
from .util import load_json


@dataclass(frozen=True)
class NeighborContext:
    previous_page: int | None
    previous_kind: str | None
    previous_text: str | None
    next_page: int | None
    next_kind: str | None
    next_text: str | None

    def pages(self) -> list[int]:
        return [page for page in (self.previous_page, self.next_page) if page is not None]

    def as_dict(self) -> dict[str, Any]:
        return {
            "previous": {
                "page": self.previous_page,
                "kind": self.previous_kind,
                "text": self.previous_text,
            },
            "next": {
                "page": self.next_page,
                "kind": self.next_kind,
                "text": self.next_text,
            },
        }


def build_neighbor_context(
    *,
    source: SourcePackage,
    page: int,
    previous_characters: int,
    next_characters: int,
    canonical_search_dirs: list[Path] | None = None,
) -> NeighborContext:
    search_dirs = canonical_search_dirs or []
    previous_page = page - 1 if page > 1 else None
    next_page = page + 1 if page < source.page_count else None
    previous_text: str | None = None
    previous_kind: str | None = None
    if previous_page is not None:
        filename = f"page-{previous_page:03d}.json"
        canonical_path = next(
            (directory / filename for directory in search_dirs if (directory / filename).is_file()),
            None,
        )
        if canonical_path:
            previous_text = structured_tail(load_json(canonical_path), previous_characters)
            previous_kind = "validated_structured_tail"
        else:
            previous_text = source.ocr_text(previous_page)[-previous_characters:]
            previous_kind = "raw_ocr_tail"

    next_text: str | None = None
    next_kind: str | None = None
    if next_page is not None:
        next_text = source.ocr_text(next_page)[:next_characters]
        next_kind = "raw_ocr_head"
    return NeighborContext(
        previous_page=previous_page,
        previous_kind=previous_kind,
        previous_text=previous_text,
        next_page=next_page,
        next_kind=next_kind,
        next_text=next_text,
    )


def build_prompt(
    *,
    specification: str,
    page_id: str,
    current_ocr: str,
    context: NeighborContext,
) -> str:
    previous = context.previous_text if context.previous_text is not None else "[none]"
    following = context.next_text if context.next_text is not None else "[none]"
    previous_label = context.previous_kind or "none"
    next_label = context.next_kind or "none"
    return f"""{specification.rstrip()}

## Run-specific evidence

CURRENT SOURCE PAGE: {page_id}

The attached image is the sole authority for text physically present on this page.

<current_page_ocr status="non_authoritative_hypothesis">
{current_ocr.rstrip()}
</current_page_ocr>

<previous_page_context kind="{previous_label}" status="continuity_only_non_authoritative">
{previous.rstrip()}
</previous_page_context>

<next_page_context kind="{next_label}" status="continuity_only_non_authoritative">
{following.rstrip()}
</next_page_context>

Return only the JSON object required by the supplied output schema.
"""
