"""Typed day-status values for the weekly-operations sidecar."""

from __future__ import annotations

import hashlib
import json
import re
from dataclasses import dataclass
from datetime import date, datetime, timedelta
from enum import StrEnum
from typing import ClassVar, Final, Literal, NewType, override

from pydantic import BaseModel, ConfigDict, Field

WEEKLY_OPERATIONS_SCHEMA: Final = "nutricoach-weekly-operations-v1"
ZERO_DIGEST: Final = "0" * 64
CustomerKey = NewType("CustomerKey", str)
CustomerIdentityDigest = NewType("CustomerIdentityDigest", str)
_DIGEST = re.compile(r"^[0-9a-f]{64}$")
_OPAQUE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,159}$")
class DayState(StrEnum):
    """Terminal timeliness states for one KST calendar day."""

    SUBMITTED = "submitted"
    MISSED = "missed"
    LATE_SUBMITTED = "late_submitted"


class WeeklyOperationsError(Exception):
    """Base typed failure for weekly-operations state."""

    __slots__: tuple[str, ...] = ("reason",)

    def __init__(self, reason: str) -> None:
        super().__init__(reason)
        self.reason: str = reason

    @override
    def __str__(self) -> str:
        return f"weekly operations failed: {self.reason}"


class WeeklyOperationsInputError(WeeklyOperationsError):
    """An append request violates the typed contract."""


class WeeklyOperationsConflict(WeeklyOperationsError):
    """An append conflicts with durable day history."""


class WeeklyOperationsCorruption(WeeklyOperationsError):
    """Durable sidecar bytes violate the hash-chain contract."""


class WeeklyOperationsAlreadyInitialized(WeeklyOperationsCorruption):
    """Atomic initialization found an already-published authority."""


class CanonicalAuthorityAlreadyRegistered(WeeklyOperationsConflict):
    """A customer already has one durable canonical authority binding."""


class WeeklyOperationsAuthorityCompromise(WeeklyOperationsCorruption):
    """A pinned authority namespace no longer names its bound inode."""


class WeeklyOperationsPlatformNotSupported(WeeklyOperationsCorruption):
    """The host cannot provide required descriptor-only publication."""


@dataclass(frozen=True, slots=True)
class CanonicalPin:
    sequence: int
    digest: str

    def __post_init__(self) -> None:
        if self.sequence < 0 or _DIGEST.fullmatch(self.digest) is None:
            raise WeeklyOperationsInputError("canonical pin")


@dataclass(frozen=True, slots=True)
class SourceLineage:
    event_id: str
    event_digest: str

    def __post_init__(self) -> None:
        if _OPAQUE.fullmatch(self.event_id) is None or _DIGEST.fullmatch(self.event_digest) is None:
            raise WeeklyOperationsInputError("source lineage")


@dataclass(frozen=True, slots=True)
class ReminderIdentity:
    reservation_id: str | None = None
    audit_id: str | None = None

    def __post_init__(self) -> None:
        for value in (self.reservation_id, self.audit_id):
            if value is not None and _OPAQUE.fullmatch(value) is None:
                raise WeeklyOperationsInputError("reminder identity")


@dataclass(frozen=True, slots=True)
class WeeklyOperationInput:
    """One requested append, parsed before the filesystem boundary."""

    customer_identity_digest: CustomerIdentityDigest
    kst_day: date
    state: DayState
    canonical: CanonicalPin
    occurred_at: datetime
    source: SourceLineage | None = None
    reminder: ReminderIdentity | None = None

    def __post_init__(self) -> None:
        if _DIGEST.fullmatch(self.customer_identity_digest) is None:
            raise WeeklyOperationsInputError("customer identity digest")
        if self.occurred_at.utcoffset() != timedelta(hours=9) or self.occurred_at.date() != self.kst_day:
            raise WeeklyOperationsInputError("occurred time must match the KST day")

    @classmethod
    def for_customer(
        cls,
        customer_key: CustomerKey,
        kst_day: date,
        state: DayState,
        canonical: CanonicalPin,
        occurred_at: datetime,
        source: SourceLineage | None = None,
        reminder: ReminderIdentity | None = None,
    ) -> WeeklyOperationInput:
        """Consume a trusted raw key and retain only its opaque identity."""
        if re.fullmatch(r"[a-z0-9][a-z0-9_-]{2,63}", customer_key) is None:
            raise WeeklyOperationsInputError("customer key")
        return cls(customer_identity_digest(customer_key), kst_day, state, canonical, occurred_at, source, reminder)


class WeeklyOperationRow(BaseModel):
    """Strict file-boundary representation of one immutable sidecar row."""

    model_config: ClassVar[ConfigDict] = ConfigDict(frozen=True, extra="forbid")
    schema_version: Literal["nutricoach-weekly-operations-v1"]
    customer_identity_digest: CustomerIdentityDigest = Field(pattern=r"^[0-9a-f]{64}$")
    kst_day: date
    state: DayState
    canonical_sequence: int = Field(ge=0)
    canonical_digest: str = Field(pattern=r"^[0-9a-f]{64}$")
    source_event_id: str | None = Field(default=None, pattern=r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,159}$")
    source_event_digest: str | None = Field(default=None, pattern=r"^[0-9a-f]{64}$")
    reminder_reservation_id: str | None = Field(default=None, pattern=r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,159}$")
    reminder_audit_id: str | None = Field(default=None, pattern=r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,159}$")
    predecessor_row_digest: str = Field(pattern=r"^[0-9a-f]{64}$")
    occurred_at_kst: datetime
    logical_key: str = Field(pattern=r"^[0-9a-f]{64}$")
    row_digest: str = Field(pattern=r"^[0-9a-f]{64}$")


@dataclass(frozen=True, slots=True)
class AppendResult:
    row: WeeklyOperationRow
    appended: bool


@dataclass(frozen=True, slots=True)
class RepairResult:
    retained_rows: int
    removed_bytes: int


def customer_identity_digest(customer_key: CustomerKey) -> CustomerIdentityDigest:
    """Irreversibly derive the durable identity at the trusted boundary."""
    if not customer_key or len(customer_key) > 1024 or "\0" in customer_key:
        raise WeeklyOperationsInputError("customer identity")
    material = f"nutricoach-weekly-operations-customer-identity-v1\0{customer_key}"
    return CustomerIdentityDigest(hashlib.sha256(material.encode()).hexdigest())


def customer_storage_digest(customer_identity: CustomerIdentityDigest) -> str:
    """Derive the opaque flat-layout filename digest."""
    material = f"nutricoach-weekly-operations-storage-v1\0{customer_identity}"
    return hashlib.sha256(material.encode()).hexdigest()


def operation_logical_key(customer_identity: CustomerIdentityDigest, kst_day: date, identity: str) -> str:
    """Return a deterministic privacy-safe logical append identity."""
    material = f"{WEEKLY_OPERATIONS_SCHEMA}\0{customer_identity}\0{kst_day.isoformat()}\0{identity}"
    return hashlib.sha256(material.encode()).hexdigest()


def canonical_weekly_row(row: WeeklyOperationRow, *, include_digest: bool) -> bytes:
    """Encode one row using the durable canonical JSON contract."""
    excluded: set[str] = set() if include_digest else {"row_digest"}
    value = row.model_dump(mode="json", exclude=excluded)
    return json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":")).encode()


def weekly_row_digest(row: WeeklyOperationRow) -> str:
    """Digest one row body without trusting its supplied row digest."""
    return hashlib.sha256(canonical_weekly_row(row, include_digest=False)).hexdigest()
