"""Missing adversarial matrix at the actual authorized Telegram host."""

from __future__ import annotations

import hashlib
from datetime import datetime
from pathlib import Path
from zoneinfo import ZoneInfo

import pytest

from checkin_cli.models import (
    ContractCheckin,
    ContractStatus,
    Event,
    EventType,
    Provenance,
)
from checkin_cli.store import CanonicalEventTransaction
from checkin_cli.weekly_operations import (
    CanonicalPin,
    CustomerKey,
    DayState,
    WeeklyOperationInput,
)
from tests.gateway._nutrition_weekly_dispatcher_cases import dispatcher_fixture

KST = ZoneInfo("Asia/Seoul")


def _event(event_id: str) -> Event:
    occurred_at = "2026-08-17T20:00:00+09:00"
    return Event(
        event_id=event_id,
        event_type=EventType.NUTRITION_CHECKIN,
        occurred_at_kst=occurred_at,
        recorded_at_kst=occurred_at,
        schema_version="2.0",
        provenance=Provenance(
            source_type="telegram",
            source_ref=f"wizard:{event_id}",
            content_sha256=hashlib.sha256(event_id.encode()).hexdigest(),
        ),
        status=ContractStatus.ACCEPTED,
        dedupe_key=f"dedupe:{event_id}",
        check_in=ContractCheckin(calories_kcal=2200),
    )


def _topic_ledger(root: Path) -> Path:
    return root / "data" / "weekly-operations-topic59.jsonl"


@pytest.mark.asyncio
async def test_corrupt_reminder_ledger_fails_before_every_provider_and_projection(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch,
) -> None:
    fixture = dispatcher_fixture(tmp_path, "reminder")
    fixture.install_due(monkeypatch)
    ledger = tmp_path / "data" / "scheduled-deliveries.jsonl"
    _ = ledger.write_bytes(b"{corrupt-reminder-ledger\n")
    before = ledger.read_bytes()
    now = datetime(2026, 8, 17, 20, tzinfo=KST)

    first = await fixture.host.run_authorized(now)
    replay = await fixture.host.run_authorized(now)

    assert first.success is False and replay.success is False
    assert first.error == replay.error == (
        "schedule delivery fence unavailable: CustomerScheduleError"
    )
    assert ledger.read_bytes() == before
    assert fixture.provider.calls == []
    assert not _topic_ledger(tmp_path).exists()
    assert fixture.coordinator.drafts == {}


@pytest.mark.asyncio
async def test_corrupt_topic59_ledger_retains_cutoff_but_blocks_card_provider(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch,
) -> None:
    fixture = dispatcher_fixture(tmp_path, "cutoff")
    fixture.install_due(monkeypatch)
    ledger = _topic_ledger(tmp_path)
    _ = ledger.write_bytes(b"{corrupt-topic59-ledger\n")
    before = ledger.read_bytes()
    now = datetime(2026, 8, 17, 23, tzinfo=KST)

    first = await fixture.host.run_authorized(now)
    replay = await fixture.host.run_authorized(now)

    rows = fixture.reminder.store.read()
    assert first.success is False and replay.success is False
    assert first.error == replay.error == (
        "weekly operations dispatch failed for client_001: ledger_corruption"
    )
    assert len(rows) == 1 and rows[0].state is DayState.MISSED
    assert ledger.read_bytes() == before
    assert fixture.provider.calls == []
    assert fixture.coordinator.drafts == {}


@pytest.mark.asyncio
async def test_canonical_sidecar_disagreement_fails_with_exact_zero_new_counts(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch,
) -> None:
    fixture = dispatcher_fixture(tmp_path, "reminder")
    fixture.install_due(monkeypatch)
    _ = fixture.reminder.store.append(
        WeeklyOperationInput.for_customer(
            CustomerKey(fixture.reminder.runtime.spec.customer_key),
            datetime(2026, 8, 17).date(),
            DayState.MISSED,
            CanonicalPin(1, "0" * 64),
            datetime(2026, 8, 17, 20, tzinfo=KST),
        )
    )
    now = datetime(2026, 8, 17, 20, tzinfo=KST)

    first = await fixture.host.run_authorized(now)
    replay = await fixture.host.run_authorized(now)

    assert first.success is False and replay.success is False
    assert len(fixture.reminder.store.read()) == 1
    assert fixture.provider.calls == []
    assert not _topic_ledger(tmp_path).exists()
    assert fixture.coordinator.drafts == {}


@pytest.mark.asyncio
async def test_response_race_at_pre_io_rebind_makes_valid_status_win(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch,
) -> None:
    fixture = dispatcher_fixture(tmp_path, "reminder")
    fixture.install_due(monkeypatch)
    transaction = CanonicalEventTransaction.for_customer_runtime(
        fixture.reminder.runtime
    )

    def respond() -> None:
        _ = transaction.append_one(_event("racing_response"))

    fixture.coordinator.run_before_owner_access(3, respond)
    now = datetime(2026, 8, 17, 20, tzinfo=KST)

    first = await fixture.host.run_authorized(now)
    replay = await fixture.host.run_authorized(now)

    snapshot = transaction.read_snapshot()
    assert first.success is False and replay.success is False
    assert tuple(event.event_id for event in snapshot.events) == ("racing_response",)
    assert fixture.provider.calls == []
    assert len(fixture.reminder.store.read()) == 1
    assert not _topic_ledger(tmp_path).exists()
    assert fixture.coordinator.drafts == {}


@pytest.mark.asyncio
async def test_monday_draft_is_owner_dm_only_and_topic59_has_no_approval_controls(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch,
) -> None:
    fixture = dispatcher_fixture(tmp_path, "cutoff")
    fixture.install_due(monkeypatch)
    now = datetime(2026, 8, 17, 23, tzinfo=KST)

    first = await fixture.host.run_authorized(now)
    replay = await fixture.host.run_authorized(now)

    assert first.success is True and replay.success is True
    assert len(fixture.reminder.store.read()) == 1
    assert len(fixture.provider.calls) == 1
    topic59 = fixture.provider.calls[0]
    assert (topic59.chat_id, topic59.topic_id) == ("review", 59)
    assert topic59.has_reply_markup is False
    assert [call for call in fixture.provider.calls if call.chat_id == "customer-chat"] == []
    assert fixture.coordinator.owner_routes == [("owner", "owner-dm", "owner")]
    assert tuple(fixture.coordinator.drafts) == ("weekly-1",)
