"""Pydantic v2 models for the wallet domain.

No FastAPI imports. Pure data shapes.
"""
from __future__ import annotations

from datetime import datetime
from enum import StrEnum
from typing import Any

from pydantic import BaseModel, ConfigDict, Field, field_validator


class RiskLevel(StrEnum):
    """Wallet risk classification."""

    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"
    CRITICAL = "critical"

    @classmethod
    def from_score(cls, score: int) -> RiskLevel:
        if score < 20:
            return cls.LOW
        if score < 50:
            return cls.MEDIUM
        if score < 80:
            return cls.HIGH
        return cls.CRITICAL


class Wallet(BaseModel):
    """A wallet identity (address + chain)."""

    model_config = ConfigDict(str_strip_whitespace=True)

    address: str = Field(..., min_length=1, max_length=256)
    chain: str = Field(default="solana", description="solana, ethereum, bsc, base, ...")
    label: str | None = Field(default=None, description="Human-readable label, e.g. 'Binance Hot Wallet'")


class TokenHolding(BaseModel):
    """A single token holding within a wallet's portfolio."""

    symbol: str
    address: str = ""
    amount: float = 0.0
    price_usd: float = 0.0
    value_usd: float = 0.0


class Transaction(BaseModel):
    """A wallet transaction summary."""

    hash: str
    type: str = "transfer"
    amount_usd: float = 0.0
    timestamp: int = 0
    block_time: datetime | None = None
    direction: str | None = Field(default=None, description="in | out | self")


class Balance(BaseModel):
    """Wallet balance + token holdings."""

    model_config = ConfigDict(str_strip_whitespace=True)

    address: str
    chain: str
    native_balance: float = 0.0
    native_symbol: str = ""
    total_value_usd: float = 0.0
    tokens: list[TokenHolding] = Field(default_factory=list)
    fetched_at: datetime = Field(default_factory=datetime.utcnow)


class ScanFlag(BaseModel):
    """A risk flag raised by a scan."""

    code: str
    severity: RiskLevel
    message: str
    evidence: dict[str, Any] = Field(default_factory=dict)


class WalletAnalysis(BaseModel):
    """Full wallet analysis — risk + tokens + recent activity."""

    address: str
    chain: str
    truncated_address: str
    risk_score: int = Field(default=0, ge=0, le=100)
    risk_level: RiskLevel
    tokens: list[TokenHolding] = Field(default_factory=list)
    recent_transactions: list[Transaction] = Field(default_factory=list)
    labels: list[str] = Field(default_factory=list, description="Known labels (e.g. 'Binance', 'Vitalik')")
    flags: list[ScanFlag] = Field(default_factory=list)
    total_value_usd: float = 0.0
    analyzed_at: datetime = Field(default_factory=datetime.utcnow)


class ScanRequest(BaseModel):
    """Request body for the wallet scan endpoint."""

    model_config = ConfigDict(str_strip_whitespace=True)

    address: str = Field(..., min_length=1, max_length=256)
    chain: str = Field(default="solana")
    tier: str = Field(default="free", description="free | pro | elite | internal")

    @field_validator("chain")
    @classmethod
    def _chain_lowercase(cls, v: str) -> str:
        return v.lower().strip()

    @field_validator("tier")
    @classmethod
    def _tier_lowercase(cls, v: str) -> str:
        return v.lower().strip()


class ScanResult(BaseModel):
    """Threat scan result."""

    address: str
    chain: str
    risk_score: int = Field(default=0, ge=0, le=100)
    risk_level: RiskLevel
    flags: list[ScanFlag] = Field(default_factory=list)
    modules_run: list[str] = Field(default_factory=list)
    scanned_at: datetime = Field(default_factory=datetime.utcnow)
