"""Record an independent legacy AFI wire vector and replay it without networking."""

from __future__ import annotations

import argparse
import json
from collections.abc import Mapping
from datetime import UTC, datetime
from pathlib import Path
from tempfile import TemporaryDirectory

import anyio
from anyio.abc import ByteStream

from rpkiparrot.config import RtrSourceConfig
from rpkiparrot.diagnostics import Recorder, replay
from rpkiparrot.models import SourceInfo, SourceUpdate
from rpkiparrot.rtr.client import RtrSession
from rpkiparrot.transports import ConnectedTransport


class FixtureStream(ByteStream):
    """Caller-owned deterministic peer bytes, independent of our encoder.

    Cache Response session 11; -10 IPv4 ASPA 65000 -> 65010; EOD serial 1,
    refresh 30 / retry 1 / expire 600. It is a protocol fixture, not RP data.
    """

    def __init__(self) -> None:
        self.remaining = bytes.fromhex(
            "0203000b00000008"
            "020b000000000014010000010000fde80000fdf2"
            "0207000b00000018000000010000001e0000000100000258"
        )

    async def send(self, item: bytes) -> None:
        await anyio.lowlevel.checkpoint()

    async def receive(self, max_bytes: int = 65536) -> bytes:
        await anyio.lowlevel.checkpoint()
        if not self.remaining:
            raise anyio.EndOfStream
        result, self.remaining = self.remaining[:max_bytes], self.remaining[max_bytes:]
        return result

    async def send_eof(self) -> None:
        pass

    async def aclose(self) -> None:
        self.remaining = b""


class DiagnosticSink:
    """Acknowledge fixture transactions; this example serves no online queries."""

    async def publish(self, update: SourceUpdate) -> None:
        assert update.source.serial == 1

    async def report(self, status: SourceInfo) -> None:
        pass


async def record_fixture(path: Path) -> None:
    """The host owns the event loop and the ordered recorder/session contexts."""
    config = RtrSourceConfig(
        id="fixture", host="unused.invalid", max_version=2, v2_profile="8210bis-10"
    )
    async with (
        Recorder(path, rtr_config=config) as recorder,
        RtrSession(
            config,
            transport_factory=recorder.wrap(ConnectedTransport(FixtureStream(), owns_stream=True)),
        ) as session,
    ):
        await session.run(DiagnosticSink())
    assert recorder.get_status().complete


def main() -> None:
    """Run a finite fixture and print explicit offline diagnostic results."""
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--backend", choices=("asyncio", "trio"), default="asyncio")
    backend = parser.parse_args().backend
    with TemporaryDirectory() as directory:
        path = Path(directory) / "fixture.jsonl"
        anyio.run(record_fixture, path, backend=backend)
        report = replay(path, reference_time=datetime(2026, 1, 1, tzinfo=UTC))
        commit = next(event for event in report.events if event.kind == "commit")
        assert report.complete and report.matched
        aspas = commit.data["aspas"]
        assert isinstance(aspas, tuple) and isinstance(aspas[0], Mapping)
        print(
            json.dumps(
                {
                    "backend": backend,
                    "complete": report.complete,
                    "matched": report.matched,
                    "afi": aspas[0]["afi"],
                    "unverified": report.unverified,
                }
            )
        )


if __name__ == "__main__":
    main()
