"""Real registered capability support for weekly reminder gateway tests."""

from __future__ import annotations

import json
from collections.abc import Callable
from dataclasses import dataclass
from datetime import datetime
from pathlib import Path
from typing import final, override
from zoneinfo import ZoneInfo

from checkin_cli.customer_coaching import (
    CustomerRegistry,
    CustomerRuntime,
    load_customer_registry,
)
from checkin_cli.store import CanonicalEventTransaction
from checkin_cli.weekly_operations import CustomerKey
from checkin_cli.weekly_operations_authority import (
    AuthorityId,
    WeeklyOperationsAuthorityRoot,
    begin_authority_initialization,
)
from checkin_cli.weekly_operations_customer_authority import (
    CanonicalCheckinCustomerAuthority,
)
from checkin_cli.weekly_operations_parent import acquire_parent_authority
from checkin_cli.weekly_operations_registration_handoff import (
    begin_canonical_authority_registration,
)
from checkin_cli.weekly_operations_store import WeeklyOperationsStore
from tests.gateway._weekly_operations_authority_support import (
    registry_identity_from_file,
    registry_identity_to_document,
)
from gateway.platforms.nutrition_weekly_operations_authority import (
    WeeklyOperationsRuntimeContext,
    parse_weekly_operations_authority,
)
from gateway.platforms.nutrition_weekly_operations_config import (
    JsonValue,
    parse_weekly_operations_config,
)
from gateway.platforms.nutrition_weekly_reminder import TelegramReminderDelivered
from gateway.platforms.nutrition_weekly_reminder_authority import (
    RegisteredWeeklyReminderCustomer,
    WeeklyOperationsTickSnapshot,
    WeeklyReminderAuthorityOwner,
    WeeklyReminderContextSource,
    WeeklyReminderOwnerInput,
    register_weekly_reminder_customer,
)
from gateway.platforms.nutrition_weekly_reminder_owner_factory import (
    weekly_reminder_consent_digest,
)

KST = ZoneInfo("Asia/Seoul")
CANDIDATE = "a" * 64
REGISTRY = "c" * 64


@final
class ReminderContextSource(WeeklyReminderContextSource):
    def __init__(self) -> None:
        self.after_snapshot: Callable[[], None] | None = None
        self.calls: int = 0

    @override
    def consent_digest(self, runtime: CustomerRuntime) -> str:
        return weekly_reminder_consent_digest(runtime)

    @override
    def current_context(
        self, runtime: CustomerRuntime, now: datetime
    ) -> WeeklyOperationsRuntimeContext:
        self.calls += 1
        if self.after_snapshot is not None:
            callback, self.after_snapshot = self.after_snapshot, None
            callback()
        return WeeklyOperationsRuntimeContext(
            CANDIDATE,
            runtime.spec.customer_key,
            "owner",
            "owner-dm",
            7,
            weekly_reminder_consent_digest(runtime),
            True,
            "weekly-operations-v1",
            now,
        )


def registry_payload(
    *, chat_id: str = "customer-chat", topic_id: str = "customer-topic",
    customer_count: int = 1,
) -> dict[str, JsonValue]:
    return {
        "version": 1,
        "owner": {"user_id": "owner", "chat_id": "owner-dm", "topic_id": "owner"},
        "customers": [{
            "customer_key": f"client_{index:03d}", "display_name": "fixture", "enabled": index == 1,
            "telegram": {
                "user_id": f"user-{index}",
                "chat_id": chat_id if index == 1 else f"{chat_id}-{index}",
                "topic_id": topic_id if index == 1 else f"{topic_id}-{index}",
            },
            "schedule": {"daily_time": "08:00", "weekly_weekday": 0, "monthly_day": 1},
            "profile": {"primary_goal": "fixture", "sleep_goal_hours": 8},
            "ai_processing_consent": {"granted": True, "recorded_on": "2026-08-01", "notice_version": "privacy-v1"},
            "plan": {"starts_on": "2026-08-01", "focus": "nutrition_90_training_10", "weeks": [
                {"week": week, "calories_kcal": 2300, "protein_g": 150, "meal_structure": ["breakfast", "lunch", "dinner"]}
                for week in range(1, 13)
            ]},
        } for index in range(1, customer_count + 1)],
    }


@dataclass(frozen=True, slots=True)
class ReminderOwnerFixture:
    registry: CustomerRegistry
    owner: WeeklyReminderAuthorityOwner
    customer: RegisteredWeeklyReminderCustomer
    customers: tuple[RegisteredWeeklyReminderCustomer, ...]
    store: WeeklyOperationsStore
    extra: dict[str, JsonValue]
    runtime: CustomerRuntime
    registry_path: Path


def reminder_owner_fixture(
    tmp_path: Path, context_source: ReminderContextSource | None = None,
    *, customer_count: int = 1, topic_id: str = "customer-topic",
) -> ReminderOwnerFixture:
    registry_path = tmp_path / "registry.json"
    _ = registry_path.write_text(json.dumps(registry_payload(customer_count=customer_count, topic_id=topic_id)), encoding="utf-8")
    registry_path.chmod(0o600)
    registry_identity = registry_identity_from_file(
        tmp_path, "registry.json"
    )
    registry = load_customer_registry(registry_path, tmp_path)
    runtime = registry.customers[0]
    authority_path = tmp_path / "weekly-authority"
    authority_path.mkdir(mode=0o700)
    parent = acquire_parent_authority(authority_path)
    authority: WeeklyOperationsAuthorityRoot | None = None
    with begin_authority_initialization(
        parent, AuthorityId("4" * 64)
    ) as initialization:
        authority = initialization.authority
        _ = initialization.binding
        initialization.acknowledge_binding()
    if authority is None:
        raise AssertionError("weekly authority initialization failed")
    customers: list[RegisteredWeeklyReminderCustomer] = []
    stores: list[WeeklyOperationsStore] = []
    for current in registry.customers:
        store = WeeklyOperationsStore.for_authority(
            authority, CustomerKey(current.spec.customer_key)
        )
        stores.append(store)
        current.customer_root.mkdir(parents=True, mode=0o700)
        current.wizard_root.mkdir(parents=True, mode=0o700)
        current.nutrition_plans_root.mkdir(parents=True, mode=0o700)
        transaction = CanonicalEventTransaction.for_customer_runtime(current)
        for path in (transaction.events_path, transaction.sequence_path):
            path.touch(mode=0o600)
            path.chmod(0o600)
        _ = transaction.read_snapshot()
        canonical: CanonicalCheckinCustomerAuthority | None = None
        with begin_canonical_authority_registration(
            current, authority
        ) as registration:
            canonical = registration.authority
            _ = registration.binding
            registration.acknowledge_binding()
        if canonical is None:
            raise AssertionError("canonical registration failed")
        customers.append(
            register_weekly_reminder_customer(current, canonical, store)
        )
    customer = customers[0]
    store = stores[0]
    base_extra: dict[str, JsonValue] = {"nutrition_coaching": {
        "operator_review": {"user_id": "owner", "chat_id": "review", "topic_id": 59},
        "weekly_operations": {"enabled": True, "reminder_time": "20:00:00", "missed_cutoff_time": "23:00:00", "weekly_weekday": 0, "feature_epoch": "weekly-operations-v1", "registry_identity_binding_digest": registry_identity.binding_digest},
    }}
    config = parse_weekly_operations_config(base_extra)
    raw_receipt: dict[str, JsonValue] = {
        "schema": "nutricoach-weekly-operations-authority-v2",
        "candidate_digest": CANDIDATE,
        "config_digest": config.digest,
        "enabled_customer_keys": [
            current.spec.customer_key for current in registry.customers
        ],
        "owner": {"user_id": "owner", "chat_id": "owner-dm", "version": 7},
        "consent_digest": weekly_reminder_consent_digest(runtime),
        "registry_identity": registry_identity_to_document(registry_identity),
        "issued_at": "2026-08-17T19:00:00+09:00",
        "expires_at": "2026-08-17T23:59:00+09:00",
        "feature_epoch": "weekly-operations-v1",
    }
    receipt = parse_weekly_operations_authority(raw_receipt)
    extra: dict[str, JsonValue] = {"nutrition_coaching": {
        "operator_review": {"user_id": "owner", "chat_id": "review", "topic_id": 59},
        "weekly_operations": {"enabled": True, "reminder_time": "20:00:00", "missed_cutoff_time": "23:00:00", "weekly_weekday": 0, "feature_epoch": "weekly-operations-v1", "registry_identity_binding_digest": registry_identity.binding_digest},
        "weekly_operations_authority": raw_receipt,
        "weekly_operations_authority_source": "operator",
    }}
    current_source = context_source or ReminderContextSource()
    owner = WeeklyReminderAuthorityOwner(
        WeeklyReminderOwnerInput(
            config, receipt, REGISTRY, tuple(customers), current_source
        )
    )
    return ReminderOwnerFixture(
        registry, owner, customer, tuple(customers), store, extra, runtime, registry_path
    )


@final
class FakeTelegramHost:
    def __init__(self) -> None:
        self.calls: int = 0

    def weekly_operations_authority_current(
        self, _snapshot: WeeklyOperationsTickSnapshot
    ) -> bool:
        return True

    async def send_weekly_reminder(
        self, chat_id: str, topic_id: str | None, text: str
    ) -> TelegramReminderDelivered:
        assert chat_id == "customer-chat"
        assert topic_id == "customer-topic"
        assert text
        self.calls += 1
        return TelegramReminderDelivered("telegram-1", "telegram-1")


@final
class ReminderOwnerCoordinator:
    def __init__(
        self, owner: WeeklyReminderAuthorityOwner, registry: CustomerRegistry
    ) -> None:
        self.owner = owner
        self.registry = registry

    def refresh_live_registry(self) -> bool:
        return True

    @property
    def weekly_reminder_authority_owner(self) -> WeeklyReminderAuthorityOwner:
        self.owner.verify_registry(self.registry)
        return self.owner


