from __future__ import annotations

from datetime import datetime
from typing import Any, Literal

from pydantic import BaseModel, ConfigDict, Field, field_validator

from app.schemas.risk_disposition import RiskDispositionAction, RiskDispositionRead

RiskObservationStatus = Literal[
    "pending_review",
    "confirmed",
    "false_positive",
    "ignored",
    "resolved",
]

RiskObservationFeedbackType = Literal[
    "confirm",
    "false_positive",
    "ignore",
    "resolve",
    "comment",
]


class RiskObservationFeedbackRead(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: str
    observation_id: str
    feedback_type: str
    action: str
    actor: str
    comment: str | None
    payload_json: dict[str, Any]
    decision: str = ""
    candidate_rule_source: str = ""
    confidence_score: float = 0.0
    escalation_target: str = ""
    supplement_required: bool = False
    created_at: datetime


class RiskObservationRead(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: str
    tenant_id: str
    observation_key: str
    subject_type: str
    subject_key: str
    subject_label: str
    claim_id: str | None
    claim_no: str
    run_id: str | None
    execution_log_id: str | None
    risk_type: str
    risk_signal: str
    title: str
    description: str
    risk_score: int
    risk_level: str
    confidence_score: float
    control_stage: str
    control_mode: str
    automation_mode: str
    source: str
    algorithm_version: str
    status: str
    feedback_status: str
    contribution_scores_json: dict[str, Any]
    baseline_json: dict[str, Any]
    evidence_json: list[Any]
    graph_node_keys_json: list[Any]
    graph_edge_keys_json: list[Any]
    policy_refs_json: list[Any]
    similar_case_claim_ids_json: list[Any]
    ontology_json: dict[str, Any]
    decision_trace_json: dict[str, Any]
    sampling_strategy: dict[str, Any] = Field(default_factory=dict)
    evaluation_case_id: str = ""
    ontology_parse_id: str = ""
    ontology_version: str = ""
    domain: str = ""
    scenario: str = ""
    intent: str = ""
    ontology_entities_json: list[Any] = Field(default_factory=list)
    risk_signals_json: list[Any] = Field(default_factory=list)
    canonical_subject_key: str = ""
    created_at: datetime
    updated_at: datetime
    feedback_items: list[RiskObservationFeedbackRead] = Field(default_factory=list)
    disposition: RiskDispositionRead | None = None
    available_actions: list[RiskDispositionAction] = Field(default_factory=list)
    read_only_reason: str = ""


class RiskObservationListRead(BaseModel):
    items: list[RiskObservationRead]
    total: int
    limit: int
    offset: int


class RiskObservationFeedbackCreate(BaseModel):
    feedback_type: RiskObservationFeedbackType
    action: str | None = Field(default=None, max_length=50)
    actor: str | None = Field(
        default=None,
        max_length=100,
        description="兼容字段；服务端始终以当前认证用户覆盖该值。",
    )
    comment: str | None = Field(default=None, max_length=1000)
    payload_json: dict[str, Any] = Field(default_factory=dict)

    @field_validator("action", "actor", "comment", mode="before")
    @classmethod
    def normalize_text(cls, value: Any) -> Any:
        if value is None:
            return None
        normalized = str(value).strip()
        return normalized or None


class RiskObservationDashboardRead(BaseModel):
    window_days: int
    total_observations: int
    pending_count: int
    risk_clue_count: int = 0
    high_or_above_count: int
    confirmed_count: int
    false_positive_count: int
    feedback_sample_count: int = 0
    total_amount: float = 0.0
    average_score: float
    level_distribution: dict[str, int] = Field(default_factory=dict)
    status_distribution: dict[str, int] = Field(default_factory=dict)
    signal_distribution: dict[str, int] = Field(default_factory=dict)
    source_distribution: dict[str, int] = Field(default_factory=dict)
    automation_distribution: dict[str, int] = Field(default_factory=dict)
    department_distribution: dict[str, int] = Field(default_factory=dict)
    expense_type_distribution: dict[str, int] = Field(default_factory=dict)
    risk_type_distribution: dict[str, int] = Field(default_factory=dict)
    supplier_distribution: dict[str, int] = Field(default_factory=dict)
    employee_grade_distribution: dict[str, int] = Field(default_factory=dict)
    daily_trend: list[dict[str, Any]] = Field(default_factory=list)
    top_risk_signals: list[dict[str, Any]] = Field(default_factory=list)
    top_departments: list[dict[str, Any]] = Field(default_factory=list)
    top_employees: list[dict[str, Any]] = Field(default_factory=list)
    top_suppliers: list[dict[str, Any]] = Field(default_factory=list)
    top_expense_types: list[dict[str, Any]] = Field(default_factory=list)
    top_rules: list[dict[str, Any]] = Field(default_factory=list)
    candidate_rule_count: int = 0
    confirmation_rate: float
    false_positive_rate: float
    recent_high_observations: list[RiskObservationRead] = Field(default_factory=list)
