"""Post-close trigger contracts and registry helpers for Deal Desk."""

from __future__ import annotations

from typing import Any, Literal

from pydantic import BaseModel, ConfigDict, Field, computed_field

from .config import DealDeskConfig

PostCloseTriggerFailureMode = Literal["block", "escalate"]
PostCloseTriggerMode = Literal["preview", "live"]
PostCloseTriggerRunStatus = Literal[
    "preview_generated",
    "executed",
    "approval_required",
    "disabled",
    "failed",
    "skipped",
]


class _DealDeskTriggerModel(BaseModel):
    model_config = ConfigDict(extra="ignore")

    def to_dict(self) -> dict[str, Any]:
        return self.model_dump(exclude_none=False, by_alias=True)

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> "_DealDeskTriggerModel":
        return cls.model_validate(data)


class PostCloseTriggerV1(_DealDeskTriggerModel):
    version: int = 1
    trigger_key: str
    label: str
    tool_name: str
    enabled: bool = True
    execution_order: int = 100
    on_failure: PostCloseTriggerFailureMode = "escalate"
    require_preview_before_live: bool = True
    preview_approved: bool = False
    supported: bool = True
    pending_preview_count: int = 0
    latest_pending_preview_run_id: str | None = None
    latest_pending_opportunity_id: str | None = None
    latest_pending_plan_path: str | None = None
    latest_pending_observed_at: str | None = None
    notes: list[str] = Field(default_factory=list)

    @computed_field(alias="$schema")
    @property
    def schema(self) -> str:
        return "PostCloseTrigger/v1"


class PostCloseTriggerRunV1(_DealDeskTriggerModel):
    version: int = 1
    run_id: str
    trigger_key: str
    trigger_label: str
    tool_name: str
    opportunity_id: str
    crm_org_id: str
    org_alias: str | None = None
    mode: PostCloseTriggerMode
    status: PostCloseTriggerRunStatus
    on_failure: PostCloseTriggerFailureMode = "escalate"
    blocking: bool = False
    observed_at: str
    result_status: str | None = None
    receipt_run_id: str | None = None
    receipt_dir: str | None = None
    pending_run_id: str | None = None
    pending_plan_path: str | None = None
    approval_receipt_id: str | None = None
    approval_receipt_path: str | None = None
    approved_at: str | None = None
    approved_by: str | None = None
    target_ids: list[str] = Field(default_factory=list)
    before: dict[str, Any] = Field(default_factory=dict)
    after: dict[str, Any] = Field(default_factory=dict)
    notes: list[str] = Field(default_factory=list)

    @computed_field(alias="$schema")
    @property
    def schema(self) -> str:
        return "PostCloseTriggerRun/v1"


_TRIGGER_DEFINITIONS: dict[str, dict[str, str]] = {
    "renewal_create_shell": {
        "label": "Renewal Shell",
        "tool_name": "dealdesk.renewal.create_shell",
    }
}


def build_post_close_trigger_registry(config: DealDeskConfig) -> list[PostCloseTriggerV1]:
    triggers: list[PostCloseTriggerV1] = []
    for item in sorted(config.post_close.triggers, key=lambda entry: (entry.execution_order, entry.trigger_key)):
        definition = _TRIGGER_DEFINITIONS.get(item.trigger_key)
        if definition is None:
            triggers.append(
                PostCloseTriggerV1(
                    trigger_key=item.trigger_key,
                    label=item.trigger_key.replace("_", " ").title(),
                    tool_name="",
                    enabled=item.enabled,
                    execution_order=item.execution_order,
                    on_failure=item.on_failure,
                    require_preview_before_live=item.require_preview_before_live,
                    preview_approved=item.preview_approved,
                    supported=False,
                    notes=[f"Unsupported post-close trigger key: {item.trigger_key}."],
                )
            )
            continue
        triggers.append(
            PostCloseTriggerV1(
                trigger_key=item.trigger_key,
                label=definition["label"],
                tool_name=definition["tool_name"],
                enabled=item.enabled,
                execution_order=item.execution_order,
                on_failure=item.on_failure,
                require_preview_before_live=item.require_preview_before_live,
                preview_approved=item.preview_approved,
                supported=True,
            )
        )
    return triggers


__all__ = [
    "PostCloseTriggerFailureMode",
    "PostCloseTriggerMode",
    "PostCloseTriggerRunStatus",
    "PostCloseTriggerV1",
    "PostCloseTriggerRunV1",
    "build_post_close_trigger_registry",
]
