from __future__ import annotations

import uuid
from datetime import datetime
from typing import Any

from sqlalchemy import CheckConstraint, DateTime, Index, String, UniqueConstraint, func
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy.types import JSON

from app.db.base_class import Base


class AIApplicationPreviewDecision(Base):
    """费用申请落单前，由服务端签发并短期持有的不可变建议快照。"""

    __tablename__ = "ai_application_preview_decisions"
    __table_args__ = (
        UniqueConstraint(
            "tenant_id",
            "id",
            name="uq_ai_application_preview_decisions_tenant_id",
        ),
        UniqueConstraint(
            "tenant_id",
            "actor_id",
            "auth_session_id",
            "issue_request_id",
            name="uq_ai_application_preview_decisions_issue_request",
        ),
        CheckConstraint(
            "status IN ('issued', 'consumed', 'expired', 'revoked')",
            name="ck_ai_application_preview_decisions_status",
        ),
        CheckConstraint(
            "decision_source IN ('heuristic', 'rule', 'hybrid', 'server_draft')",
            name="ck_ai_application_preview_decisions_source",
        ),
        CheckConstraint(
            "consumed_action IS NULL OR consumed_action IN ('save_draft', 'submit')",
            name="ck_ai_application_preview_decisions_consumed_action",
        ),
        CheckConstraint(
            "status != 'consumed' OR ("
            "consumed_action IS NOT NULL AND consumed_request_id IS NOT NULL AND "
            "consumed_claim_id IS NOT NULL AND consumed_business_event_id IS NOT NULL AND "
            "consumed_final_fingerprint IS NOT NULL AND consumed_at IS NOT NULL)",
            name="ck_ai_application_preview_decisions_consumed_fields",
        ),
        CheckConstraint(
            "expires_at > created_at",
            name="ck_ai_application_preview_decisions_expiry",
        ),
        Index(
            "ix_ai_application_preview_decisions_actor_status_expiry",
            "tenant_id",
            "actor_id",
            "status",
            "expires_at",
        ),
        Index(
            "ix_ai_application_preview_decisions_conversation",
            "tenant_id",
            "conversation_id",
            "created_at",
        ),
    )

    id: Mapped[str] = mapped_column(
        String(36),
        primary_key=True,
        default=lambda: str(uuid.uuid4()),
    )
    tenant_id: Mapped[str] = mapped_column(String(64), nullable=False)
    actor_id: Mapped[str] = mapped_column(String(120), nullable=False)
    auth_session_id: Mapped[str] = mapped_column(String(120), nullable=False)
    conversation_id: Mapped[str] = mapped_column(String(120), nullable=False, default="")
    decision_type: Mapped[str] = mapped_column(String(80), nullable=False)
    decision_source: Mapped[str] = mapped_column(String(20), nullable=False)
    field_keys_json: Mapped[list[str]] = mapped_column(JSON, nullable=False, default=list)
    field_fingerprints_json: Mapped[dict[str, str]] = mapped_column(
        JSON,
        nullable=False,
        default=dict,
    )
    snapshot_fingerprint: Mapped[str] = mapped_column(String(80), nullable=False)
    fingerprint_key_version: Mapped[str] = mapped_column(String(40), nullable=False)
    source_version_json: Mapped[dict[str, Any]] = mapped_column(
        JSON,
        nullable=False,
        default=dict,
    )
    status: Mapped[str] = mapped_column(String(20), nullable=False, default="issued")
    issue_request_id: Mapped[str] = mapped_column(String(120), nullable=False)
    consumed_action: Mapped[str | None] = mapped_column(String(30), nullable=True)
    consumed_request_id: Mapped[str | None] = mapped_column(String(120), nullable=True)
    consumed_claim_id: Mapped[str | None] = mapped_column(String(36), nullable=True)
    consumed_business_event_id: Mapped[str | None] = mapped_column(String(36), nullable=True)
    consumed_final_fingerprint: Mapped[str | None] = mapped_column(String(80), nullable=True)
    expires_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
    consumed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        server_default=func.now(),
    )
