# Copyright (c) 2026 Nous Research
"""Typed identities for a sealed channel-inbox registry migration."""

from __future__ import annotations

from dataclasses import dataclass
from enum import StrEnum
from typing import override

from gateway.platforms.telegram_channel_inbox_config import ChannelInboxAuthority


class MigrationRejectReason(StrEnum):
    """Stable fail-closed migration reasons."""

    AFTER = "after"
    APPROVAL = "approval"
    AUTHORITY = "authority"
    BEFORE = "before"
    COLLISION = "collision"
    CONSENT = "consent"
    CUSTOMER = "customer"
    DIGEST = "digest"
    ENABLED = "enabled"
    IDENTITY = "identity"
    PROPOSAL = "proposal"
    REGISTRY = "registry"
    TOPIC = "topic"


@dataclass(frozen=True, slots=True)
class ChannelInboxMigrationError(ValueError):
    """The registry migration failed before external persistence."""

    reason: MigrationRejectReason

    @override
    def __str__(self) -> str:
        """Return the machine-consumed reason.

        Returns:
            Stable rejection reason.

        """
        return self.reason.value


@dataclass(frozen=True, slots=True)
class TelegramRoute:
    """Exact Telegram delivery address."""

    user_id: str
    chat_id: str
    topic_id: str


@dataclass(frozen=True, slots=True)
class ChannelInboxMigrationRequest:
    """Owner-requested route transition bound to one candidate."""

    customer_key: str
    telegram_user_id: str
    direct_messages_topic_id: str
    authority: ChannelInboxAuthority
    capability_digest: str


@dataclass(frozen=True, slots=True)
class ChannelInboxMigrationProposal:
    """Immutable input to a later permission-sealed live controller."""

    customer_key: str
    before_sha256: str
    after_sha256: str
    old_route: TelegramRoute
    new_route: TelegramRoute
    authority: ChannelInboxAuthority
    capability_digest: str
    proposal_digest: str

    @property
    def candidate_digest(self) -> str:
        """Return the candidate bound by the Telegram authority."""
        return self.authority.candidate_digest

    @property
    def approval_phrase(self) -> str:
        """Return the exact one-use owner approval phrase.

        Returns:
            Exact phrase bound to this proposal.

        """
        return f"AUTHORIZE NUTRICOACH CHANNEL INBOX ROUTE V1 {self.proposal_digest}"
