from __future__ import annotations

import asyncio
from datetime import date
from pathlib import Path
from types import SimpleNamespace

import gateway.platforms.dualcoach_activation_cutover as cutover_module
from gateway.platforms.telegram import TelegramAdapter
from gateway.platforms.telegram_activation_notice import ActivationNoticeStore

from .new_customer_consent_testkit import awaiting_consent


def test_committed_activation_reserves_one_customer_completion_notice(
    tmp_path: Path,
) -> None:
    profile = tmp_path / "profile"
    profile.mkdir(mode=0o700)
    (profile / "data").mkdir(mode=0o700)
    activation = profile / "data/customer-activation-journal.json"
    activation.write_text(
        '{"customer_id":"customer_001","state":"committed"}',
        encoding="utf-8",
    )
    activation.chmod(0o600)
    membership = tmp_path / "membership.json"
    membership.write_text('{"schema":"membership"}', encoding="utf-8")
    membership.chmod(0o600)
    _, session = awaiting_consent(profile)
    customer = SimpleNamespace(
        plan={"starts_on": "2026-09-01"},
        schedule={"daily_time": "08:00"},
        telegram={"user_id": "10", "chat_id": "10", "topic_id": "0"},
    )
    cutover_module._finalize_membership_activation_binding(
        profile,
        membership,
        customer_id=session.customer_key,
    )
    activation.write_text(
        '{"customer_id":"customer_002","state":"committed"}',
        encoding="utf-8",
    )
    activation.chmod(0o600)
    cutover_module._finalize_membership_activation_binding(
        profile,
        membership,
        customer_id=session.customer_key,
    )

    cutover_module._reserve_activation_completion_notice(
        profile,
        customer,
        session,
        membership_evidence_path=membership,
    )
    cutover_module._reserve_activation_completion_notice(
        profile,
        customer,
        session,
        membership_evidence_path=membership,
    )

    notices = ActivationNoticeStore(profile).latest()
    assert len(notices) == 1
    assert notices[0].state == "prepared"
    assert notices[0].customer_key == "customer_001"
    assert notices[0].destination == {
        "user_id": "10",
        "chat_id": "10",
        "topic_id": "0",
    }


def test_activation_notice_defers_until_customer_start_date(
    tmp_path: Path,
) -> None:
    store = ActivationNoticeStore(tmp_path)
    notice = store.reserve(
        customer_key="customer_001",
        starts_on="2026-09-01",
        daily_time="08:00",
        destination={"user_id": "10", "chat_id": "10", "topic_id": "0"},
        authority_digest="a" * 64,
    )
    destination = SimpleNamespace(user_id="10", chat_id="10", topic_id="0")

    class Coordinator:
        @staticmethod
        def refresh_live_registry() -> bool:
            return True

        @staticmethod
        def customer(_customer_key: str) -> object:
            return SimpleNamespace(spec=SimpleNamespace(telegram=destination))

        @staticmethod
        def customer_transport_allowed(
            _customer_key: str,
            _destination: object,
            *,
            kst_date: date,
        ) -> bool:
            return kst_date >= date(2026, 9, 1)

    sends: list[str] = []

    async def send_topic(**_kwargs: object) -> object:
        sends.append("sent")
        return SimpleNamespace(message_id=700)

    adapter = object.__new__(TelegramAdapter)
    adapter._send_nutrition_topic = send_topic

    before = asyncio.run(
        adapter._drain_activation_completion_notices(
            tmp_path,
            Coordinator(),
            kst_date=date(2026, 8, 31),
        )
    )
    assert before == ()
    assert sends == []
    assert ActivationNoticeStore(tmp_path).latest() == (notice,)

    on_start = asyncio.run(
        adapter._drain_activation_completion_notices(
            tmp_path,
            Coordinator(),
            kst_date=date(2026, 9, 1),
        )
    )
    assert on_start == ()
    assert sends == ["sent"]
    assert ActivationNoticeStore(tmp_path).latest()[0].state == "sent_audited"
