"""Real-store fixtures and contract-preserving fake provider for Todo 5."""

from __future__ import annotations

from dataclasses import dataclass
from datetime import date, datetime
from enum import StrEnum
from pathlib import Path
from typing import Never, assert_never
from zoneinfo import ZoneInfo

import anyio

from checkin_cli.models import Event
from checkin_cli.weekly_operations import CustomerKey
from checkin_cli.weekly_operations_lifecycle import (
    ProviderDelivered,
    ProviderRejected,
    ReminderProviderKnownFailure,
    ReminderProviderUnknown,
)
from checkin_cli.weekly_reminder_ledger_authority import (
    acquire_registered_weekly_reminder_ledger_authority,
)
from checkin_cli.weekly_reminder_route import bind_registered_weekly_reminder_route
from checkin_cli.weekly_reminder_authority import (
    BoundWeeklyReminderCustomer,
    WeeklyReminderBindingInput,
    WeeklyReminderAuthorizationFacts,
    seal_weekly_reminder_authorization,
    WeeklyReminderRequest,
    bind_weekly_reminder_customer,
)
from tests._weekly_operations_correlation_support import (
    CanonicalFixture,
    StoreFixture,
    registered_source_at,
    store_at,
)

CUSTOMER = CustomerKey("pilot_customer_001")
DAY = date(2026, 8, 17)
KST = ZoneInfo("Asia/Seoul")


class ProviderMode(StrEnum):
    SENT = "sent"
    REJECTED = "rejected"
    KNOWN_FAILURE = "known_failure"
    UNKNOWN = "unknown"
    BLOCKED = "blocked"


def _provider_mode(value: ProviderMode) -> ProviderMode | str:
    return value


def _invalid_mode(value: str) -> Never:
    raise AssertionError(f"invalid provider mode: {value}")


class FakeReminderProvider:
    """Mutable fake whose calls preserve provider uncertainty and bound routing."""

    def __init__(self, mode: ProviderMode = ProviderMode.SENT) -> None:
        self.mode: ProviderMode = mode
        self.calls: int = 0
        self.entered: anyio.Event = anyio.Event()
        self.release: anyio.Event = anyio.Event()
        self.bound_digests: list[str] = []

    async def send(
        self, bound_customer: BoundWeeklyReminderCustomer
    ) -> ProviderDelivered | ProviderRejected:
        self.calls += 1
        self.bound_digests.append(bound_customer.authority_digest)
        assert bound_customer.route_chat_id == "chat"
        match _provider_mode(self.mode):
            case ProviderMode.SENT:
                return ProviderDelivered("provider-receipt-1", "message-1")
            case ProviderMode.REJECTED:
                return ProviderRejected("explicit_no_send")
            case ProviderMode.KNOWN_FAILURE:
                raise ReminderProviderKnownFailure("known_no_send")
            case ProviderMode.UNKNOWN:
                raise ReminderProviderUnknown
            case ProviderMode.BLOCKED:
                self.entered.set()
                await self.release.wait()
                return ProviderDelivered("provider-receipt-1", "message-1")
            case _ as unreachable:
                assert_never(_invalid_mode(unreachable))


@dataclass(frozen=True, slots=True)
class LifecycleFixture:
    stores: StoreFixture
    canonical: CanonicalFixture
    request: WeeklyReminderRequest

    def close(self) -> None:
        self.request.bound_customer.ledger.close()
        self.canonical.close()
        self.stores.close()


def binding_input(
    root: Path,
    stores: StoreFixture,
    canonical: CanonicalFixture,
    *,
    customer: CustomerKey = CUSTOMER,
) -> WeeklyReminderBindingInput:
    proof = seal_weekly_reminder_authorization(
        WeeklyReminderAuthorizationFacts(
        customer,
        "a" * 64,
        "b" * 64,
        "e" * 64,
        "c" * 64,
        "d" * 64,
        "weekly-operations-v1",
        bind_registered_weekly_reminder_route(canonical.runtime),
        )
    )
    return WeeklyReminderBindingInput(
        proof,
        acquire_registered_weekly_reminder_ledger_authority(
            canonical.source, stores.store
        ),
        canonical.source,
        stores.store,
    )


def fixture_at(root: Path, now: datetime, *events: Event) -> LifecycleFixture:
    stores = store_at(root / "authority")
    canonical = registered_source_at(
        root / "customer", CUSTOMER, *events, registry_authority=stores.authority
    )
    bound = bind_weekly_reminder_customer(binding_input(root, stores, canonical))
    return LifecycleFixture(
        stores,
        canonical,
        WeeklyReminderRequest(bound, DAY, now),
    )
