from __future__ import annotations

from datetime import datetime
from decimal import Decimal
from typing import Literal

from pydantic import BaseModel, Field


class CfoValueMoneyRead(BaseModel):
    currency: str
    amount: Decimal


class CfoValueWindowRead(BaseModel):
    start: datetime
    end: datetime
    as_of: datetime
    timezone: str = "Asia/Shanghai"


class CfoValueSourceRead(BaseModel):
    system: Literal["savings_ledger"] = "savings_ledger"
    ledger_revision: str = "20260716_0015"
    generated_at: datetime
    freshness_at: datetime | None = None
    data_status: Literal["complete", "empty", "partial"]
    opportunity_count: int = 0
    realization_count: int = 0
    coverage_notes: list[str] = Field(default_factory=list)


class CfoValueCashKpiRead(BaseModel):
    key: Literal["verified_net_cash_savings"] = "verified_net_cash_savings"
    label: str = "财务确认净现金节省"
    status: Literal["available", "empty"]
    values: list[CfoValueMoneyRead] = Field(default_factory=list)
    confirmed_realization_count: int = 0
    definition: str


class CfoValueUnavailableKpiRead(BaseModel):
    key: Literal[
        "verified_releasable_labor_value",
        "safe_straight_through_rate",
    ]
    label: str
    status: Literal["unavailable", "collecting"]
    reason: str
    required_inputs: list[str] = Field(default_factory=list)


class CfoValueKpisRead(BaseModel):
    verified_cash: CfoValueCashKpiRead
    releasable_labor: CfoValueUnavailableKpiRead
    safe_straight_through: CfoValueUnavailableKpiRead


class CfoValueFunnelStageRead(BaseModel):
    key: Literal[
        "estimated",
        "in_progress",
        "actual_pending",
        "verified",
        "reversed",
        "rejected_or_expired",
    ]
    label: str
    count: int
    values: list[CfoValueMoneyRead] = Field(default_factory=list)


class CfoValueFunnelRead(BaseModel):
    stages: list[CfoValueFunnelStageRead] = Field(default_factory=list)
    mature_estimated_values: list[CfoValueMoneyRead] = Field(default_factory=list)
    verified_values: list[CfoValueMoneyRead] = Field(default_factory=list)
    realization_rate_by_currency: dict[str, Decimal | None] = Field(default_factory=dict)


class CfoValueTrendPointRead(BaseModel):
    period: str
    currency: str
    verified_net: Decimal = Decimal("0")
    actual_pending: Decimal = Decimal("0")
    reversal: Decimal = Decimal("0")


class CfoValueBreakdownItemRead(BaseModel):
    dimension: str
    dimension_id: str
    dimension_name: str
    opportunity_count: int
    verified_values: list[CfoValueMoneyRead] = Field(default_factory=list)
    estimated_values: list[CfoValueMoneyRead] = Field(default_factory=list)


class CfoValueBreakdownGroupRead(BaseModel):
    dimension: str
    items: list[CfoValueBreakdownItemRead] = Field(default_factory=list)


class CfoValueGuardrailRead(BaseModel):
    key: str
    label: str
    status: Literal["ok", "attention", "unavailable"]
    count: int | None = None
    values: list[CfoValueMoneyRead] = Field(default_factory=list)
    rate: Decimal | None = None
    reason: str = ""


class CfoValueDataQualityRead(BaseModel):
    pending_confirmation_count: int = 0
    business_state_only_count: int = 0
    pending_dedupe_count: int = 0
    missing_fx_count: int = 0
    missing_evidence_count: int = 0
    actual_over_estimate_count: int = 0
    notes: list[str] = Field(default_factory=list)


class CfoValueFiltersRead(BaseModel):
    department_id: str | None = None
    project_code: str | None = None
    expense_type: str | None = None
    supplier_id: str | None = None
    city: str | None = None
    owner_id: str | None = None
    source_type: str | None = None
    value_kind: Literal["cash", "labor"] | None = None


class CfoValueDashboardRead(BaseModel):
    window: CfoValueWindowRead
    source: CfoValueSourceRead
    filters: CfoValueFiltersRead
    kpis: CfoValueKpisRead
    funnel: CfoValueFunnelRead
    trend: list[CfoValueTrendPointRead] = Field(default_factory=list)
    breakdowns: list[CfoValueBreakdownGroupRead] = Field(default_factory=list)
    guardrails: list[CfoValueGuardrailRead] = Field(default_factory=list)
    data_quality: CfoValueDataQualityRead
