"""Typed weekly reminder planning and owner boundary tests."""

from __future__ import annotations

from datetime import date, datetime
from typing import final
from zoneinfo import ZoneInfo

import pytest

from checkin_cli.weekly_operations_schedule_host_models_r4 import CustomerScheduleTask
from gateway.platforms.nutrition_weekly_reminder import TelegramReminderRejected
from gateway.platforms.nutrition_weekly_reminder_authority import WeeklyReminderOwnerError
from gateway.platforms.telegram_weekly_reminder import (
    WeeklySchedulePlanningIncident,
    send_weekly_operations_task,
    weekly_schedule_policy,
)

KST = ZoneInfo("Asia/Seoul")


def test_enabled_missing_external_schedule_policy_is_typed_incident(
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    import checkin_cli.weekly_operations_schedule_host_models_r4 as schedule_models

    monkeypatch.delattr(schedule_models, "WeeklyOperationsSchedulePolicy")
    with pytest.raises(WeeklySchedulePlanningIncident, match="policy is unavailable"):
        _ = weekly_schedule_policy(("client_001",))


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

    async def send_weekly_reminder(
        self, chat_id: str, topic_id: str | None, text: str
    ) -> TelegramReminderRejected:
        self.calls += 1
        return TelegramReminderRejected(f"unexpected:{chat_id}:{topic_id}:{text}")


@final
class InvalidOwnerCoordinator:
    def refresh_live_registry(self) -> bool:
        return True

    @property
    def weekly_reminder_authority_owner(self) -> None:
        return None


@pytest.mark.asyncio
async def test_invalid_owner_protocol_is_typed_before_provider() -> None:
    host = NoCallHost()
    task = CustomerScheduleTask("client_001", "reminder", date(2026, 8, 17))

    with pytest.raises(WeeklyReminderOwnerError, match="owner is invalid"):
        _ = await send_weekly_operations_task(
            host,
            InvalidOwnerCoordinator(),
            task,
            local_now=datetime(2026, 8, 17, 20, tzinfo=KST),
        )
    assert host.calls == 0
