"""Pure contract for the NutriCoach v1.5 seven-day observer."""

from __future__ import annotations

from dataclasses import dataclass
from datetime import date, datetime
from enum import StrEnum
from typing import Final

WINDOW_START: Final = datetime.fromisoformat("2026-09-01T00:00:00+09:00")
WINDOW_END: Final = datetime.fromisoformat("2026-09-08T00:00:00+09:00")
FIRST_DAY_DEADLINE: Final = datetime.fromisoformat("2026-08-31T23:05:00+09:00")
CANDIDATE: Final = "81a7a06ec2e7a1595784c92ab61df0df7e138d13a2620d9a917e94999e7f7a04"


class ObserverPhase(StrEnum):
    PRE_WINDOW = "pre_window"
    IN_WINDOW = "in_window"
    COMPLETE = "complete"


@dataclass(frozen=True, slots=True)
class RuntimeSnapshot:
    active: bool
    candidate_matches: bool
    channel_inbox_off: bool
    committed: bool
    capacity: int
    journal_clean: bool
    nrestarts: int
    telegram_sockets: int
    weekly_enabled: bool
    day_status_days: frozenset[date]


@dataclass(frozen=True, slots=True)
class Observation:
    phase: ObserverPhase
    passed: bool
    failures: tuple[str, ...]


def evaluate(snapshot: RuntimeSnapshot, now: datetime) -> Observation:
    """Evaluate one immutable production snapshot."""
    phase = (
        ObserverPhase.PRE_WINDOW
        if now < WINDOW_START
        else ObserverPhase.IN_WINDOW
        if now < WINDOW_END
        else ObserverPhase.COMPLETE
    )
    checks = (
        (snapshot.active, "service_active"),
        (snapshot.candidate_matches, "candidate_authority"),
        (snapshot.channel_inbox_off, "channel_inbox"),
        (snapshot.committed, "live_receipts"),
        (snapshot.capacity == 5, "capacity"),
        (snapshot.journal_clean, "service_journal"),
        (snapshot.nrestarts == 0, "service_restarts"),
        (snapshot.telegram_sockets >= 2, "telegram_connection"),
        (snapshot.weekly_enabled, "weekly_scheduler"),
    )
    failures = [label for passed, label in checks if not passed]
    if now >= FIRST_DAY_DEADLINE and date(2026, 8, 31) not in snapshot.day_status_days:
        failures.append("first_day_status")
    return Observation(phase, not failures, tuple(failures))
