"""The version-aware reader — load a fed-resources payload, honest-absence on failure.

This is what the engine and the web read through: a missing file is ``UNKNOWN``,
an unparseable / unknown-version / schema-violating payload is ``UNREADABLE`` —
never a guess, never a crash, never stale-shown-as-current.
"""

from __future__ import annotations

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

from ._schemas import identify, validate_payload
from .states import SyncState


@dataclass(frozen=True)
class ReadResult:
    ok: bool
    kind: str | None
    payload: Any | None
    state: SyncState | None
    reason: str | None
    errors: tuple[str, ...] = ()


def read_payload(payload: Any, *, validate: bool = True) -> ReadResult:
    """Identify + (optionally) validate an in-memory payload."""
    ident = identify(payload)
    if not ident.ok:
        return ReadResult(False, None, None, SyncState.UNREADABLE, ident.reason)
    kind = payload.get("kind") if isinstance(payload, dict) else None
    if validate:
        errors = tuple(validate_payload(payload))
        if errors:
            return ReadResult(
                False, kind, payload, SyncState.UNREADABLE, "schema validation failed", errors
            )
    return ReadResult(True, kind, payload, None, None)


def read_file(path: str | Path, *, validate: bool = True) -> ReadResult:
    """Read a JSON payload from disk; absence → UNKNOWN, corruption → UNREADABLE."""
    path = Path(path)
    try:
        text = path.read_text(encoding="utf-8")
    except FileNotFoundError:
        return ReadResult(False, None, None, SyncState.UNKNOWN, f"not found: {path}")
    except OSError as exc:
        return ReadResult(False, None, None, SyncState.UNREADABLE, f"unreadable: {exc}")
    try:
        payload = json.loads(text)
    except json.JSONDecodeError as exc:
        return ReadResult(False, None, None, SyncState.UNREADABLE, f"invalid JSON: {exc}")
    return read_payload(payload, validate=validate)
