"""Privacy-safe public values for weekly-operations aggregates."""

from __future__ import annotations

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

__all__: Final = ("PriorWeekComparison", "WeeklyOperationsSummary", "WeightTrend")


class WeightTrend(StrEnum):
    """Bounded direction derived from active check-in weights."""

    INCREASING = "increasing"
    STABLE = "stable"
    DECREASING = "decreasing"
    INSUFFICIENT_DATA = "insufficient_data"


@dataclass(frozen=True, slots=True)
class PriorWeekComparison:
    """Aggregate-only change from the immediately preceding calendar week."""

    submitted_count_delta: int
    late_count_delta: int
    missed_count_delta: int
    completed_days_delta: int
    adherence_percent_delta: float


@dataclass(frozen=True, slots=True)
class WeeklyOperationsSummary:
    """One privacy-safe Monday-through-Sunday operating aggregate."""

    starts_on: date
    ends_on: date
    window_start_kst: datetime
    window_end_kst: datetime
    submitted_count: int
    late_count: int
    missed_count: int
    completed_days: int
    calendar_days: int
    adherence_percent: float
    weight_trend: WeightTrend
    reminder_sent_count: int
    reminder_incident_count: int
    prior_week_comparison: PriorWeekComparison | None

    def to_json(self) -> str:
        """Serialize only aggregate fields with deterministic JSON bytes."""
        comparison = self.prior_week_comparison
        payload = {
            "adherence_percent": self.adherence_percent,
            "calendar_days": self.calendar_days,
            "completed_days": self.completed_days,
            "ends_on": self.ends_on.isoformat(),
            "late_count": self.late_count,
            "missed_count": self.missed_count,
            "prior_week_comparison": None
            if comparison is None
            else {
                "adherence_percent_delta": comparison.adherence_percent_delta,
                "completed_days_delta": comparison.completed_days_delta,
                "late_count_delta": comparison.late_count_delta,
                "missed_count_delta": comparison.missed_count_delta,
                "submitted_count_delta": comparison.submitted_count_delta,
            },
            "reminder_incident_count": self.reminder_incident_count,
            "reminder_sent_count": self.reminder_sent_count,
            "starts_on": self.starts_on.isoformat(),
            "submitted_count": self.submitted_count,
            "weight_trend": self.weight_trend.value,
            "window_end_kst": self.window_end_kst.isoformat(),
            "window_start_kst": self.window_start_kst.isoformat(),
        }
        return json.dumps(payload, ensure_ascii=False, sort_keys=True, separators=(",", ":"))
