"""Typed contract for nutrition start readiness."""

from __future__ import annotations

import re
from collections.abc import Mapping
from dataclasses import dataclass
from datetime import timedelta, timezone

KST = timezone(timedelta(hours=9))
CUSTOMER_KEY = re.compile(r"^[a-z0-9][a-z0-9_-]{0,63}$")
DIGEST_PATTERN = re.compile(r"^[0-9a-f]{64}$")

NUTRITION_READINESS_REASON_CODES = frozenset([
    "baseline_missing", "baseline_schema_invalid", "baseline_not_customer_attested",
    "baseline_owner_review_missing", "customer_not_adult",
    "pregnancy_breastfeeding_requires_clinical_review", "medical_clearance_required",
    "measurement_implausible", "goal_trajectory_unsafe", "restriction_kb_missing",
    "restriction_kb_stale", "restriction_kb_unapproved", "restriction_sources_incomplete",
    "customer_restrictions_unresolved", "hard_contraindication_unresolved",
    "calculation_missing", "calculation_method_unapproved", "calculation_inputs_stale",
    "calculation_review_missing", "weekly_targets_incomplete", "adjustment_policy_missing",
    "adjustment_policy_unapproved", "privacy_consent_missing", "authority_receipt_stale",
    "feature_flags_enabled", "delivery_enabled", "readiness_private_mode_invalid",
    "readiness_receipt_missing", "readiness_receipt_invalid",
])

BASELINE_FIELDS = frozenset([
    "schema_version", "customer_key", "adult_age", "equation_sex_basis", "height_cm",
    "weight_kg", "activity_category", "activity_rationale", "goal_type",
    "target_weight_kg", "target_date", "maintenance_intent", "dietary_preferences",
    "disliked_foods", "allergies", "intolerances", "religious_ethical_exclusions",
    "conditions", "medications", "pregnancy_breastfeeding", "cooking_access",
    "budget_band", "meal_count", "schedule_constraints", "customer_attested_at_kst",
    "owner_review_receipt",
    "input_reconciliation_digest", "digest",
])
KB_FIELDS = frozenset([
    "schema_version", "knowledge_version", "effective_at_kst", "reviewed_at_kst",
    "reviewed_by", "approved", "sources", "allergens", "intolerances",
    "religious_ethical_exclusions", "medication_condition_rules",
    "hard_contraindications", "cross_contact_rules", "substitution_rules", "digest",
])
CALCULATION_FIELDS = frozenset([
    "schema_version", "method_id", "method_version", "baseline_digest",
    "restriction_kb_digest", "normalized_inputs_digest", "bmr_kcal", "tdee_kcal",
    "minimum_calories_kcal", "maximum_calories_kcal", "activity_assumption",
    "goal_trajectory", "goal_trajectory_safe", "safe_rate_guardrail", "weeks",
    "requested_target_weight_kg", "requested_target_date",
    "requested_trajectory_within_guardrail", "recommended_target_date",
    "reviewed_by", "reviewed_at_kst", "review_decision", "digest",
])
RECONCILIATION_FIELDS = frozenset([
    "schema_version", "baseline_digest", "restriction_kb_digest", "resolution_status",
    "unresolved_hard_contraindications", "reviewed_by", "reviewed_at_kst", "digest",
])
POLICY_FIELDS = frozenset([
    "schema_version", "policy_version", "effective_at_kst", "approved",
    "minimum_observation_days", "weight_trend_method", "adherence_inputs",
    "actual_intake_inputs", "activity_change_inputs", "adjustment_thresholds",
    "maximum_step_kcal", "escalation_rules", "safety_stop_rules",
    "manual_override_receipt_required", "reviewed_by", "digest",
])


@dataclass(frozen=True, slots=True)
class NutritionReadinessAudit:
    ready: bool
    checks: Mapping[str, bool]
    digests: Mapping[str, str]
    reason_codes: tuple[str, ...]

    def to_dict(self) -> dict[str, object]:
        return {
            "schema_version": "nutrition_start_readiness_v1",
            "ready": self.ready,
            "checks": dict(self.checks),
            "digests": dict(self.digests),
            "reason_codes": list(self.reason_codes),
        }


class NutritionReadinessError(ValueError):
    """Raised when activation lacks committed nutrition readiness."""
