from __future__ import annotations

from typing import Any, Literal

from pydantic import BaseModel, Field

Quality = Literal["fresh", "stale", "partial", "unavailable", "unknown"]
PolicyStatus = Literal["within_range", "below_range", "above_range", "not_assessable"]


class PolicyAllocationInput(BaseModel):
    asset_class: Literal["cash", "equity", "crypto", "other"]
    target_pct: str
    lower_pct: str
    upper_pct: str


class PolicyPreviewRequest(BaseModel):
    base_currency: Literal["CHF", "EUR", "USD"]
    effective_from: str
    horizon: str | None = Field(default=None, max_length=120)
    objective: str | None = Field(default=None, max_length=2000)
    liquidity_reserve: str | None = Field(default=None, max_length=120)
    monthly_contribution: str | None = Field(default=None, max_length=120)
    max_single_position_pct: str | None = Field(default=None, max_length=120)
    max_crypto_pct: str | None = Field(default=None, max_length=120)
    rebalance_tolerance_pct: str | None = Field(default=None, max_length=120)
    min_transaction_amount: str | None = Field(default=None, max_length=120)
    benchmarks: list[dict[str, Any]] = Field(default_factory=list)
    restrictions: list[str] = Field(default_factory=list)
    allocations: list[PolicyAllocationInput] = Field(min_length=1, max_length=4)


class PolicyConfirmRequest(PolicyPreviewRequest):
    preview_id: str = Field(min_length=1, max_length=100)
    confirmation_id: str = Field(min_length=1, max_length=100)
    confirm: bool


class PolicyPreviewResponse(BaseModel):
    preview_id: str
    confirmation_id: str
    valid: bool
    errors: list[str]
    allocations: list[dict[str, str]]
    summary: str


class PolicyConfirmResponse(BaseModel):
    policy_id: str
    version: int
    audit_id: str
    idempotent: bool


class PolicyAllocationResponse(BaseModel):
    asset_class: str
    target_pct: str
    lower_pct: str
    upper_pct: str


class PortfolioPolicyResponse(BaseModel):
    policy_id: str
    version: int
    is_active: bool
    effective_from: str
    previous_policy_id: str | None = None
    base_currency: str
    horizon: str | None = None
    objective: str | None = None
    liquidity_reserve: str | None = None
    monthly_contribution: str | None = None
    max_single_position_pct: str | None = None
    max_crypto_pct: str | None = None
    rebalance_tolerance_pct: str | None = None
    min_transaction_amount: str | None = None
    benchmarks: list[Any] = Field(default_factory=list)
    restrictions: list[Any] = Field(default_factory=list)
    allocations: list[PolicyAllocationResponse]
    audit_id: str
    created_at: str


class ActivePortfolioPolicyResponse(BaseModel):
    configured: bool
    policy: PortfolioPolicyResponse | None = None


class PolicyHistoryItem(BaseModel):
    policy_id: str
    version: int
    is_active: bool
    effective_from: str
    previous_policy_id: str | None = None
    base_currency: str
    horizon: str | None = None
    objective: str | None = None
    created_at: str
    audit_id: str


class PolicyEvaluationRow(PolicyAllocationResponse):
    current_pct: str | None = None
    status: PolicyStatus
    reason: str | None = None


class PolicyEvaluationResponse(BaseModel):
    configured: bool
    version: int | None = None
    effective_from: str | None = None
    data_quality_status: Quality
    rows: list[PolicyEvaluationRow]
    reason: str | None = None
