"""Pydantic models for all MeshLedger API types."""

from __future__ import annotations

from datetime import datetime
from enum import Enum
from typing import Any, Dict, List, Optional

from pydantic import BaseModel, Field


# --- Enums ---


class Chain(str, Enum):
    BASE = "base"
    SOLANA = "solana"


class Token(str, Enum):
    USDC = "USDC"
    USDT = "USDT"
    ETH = "ETH"
    WBTC = "WBTC"
    SOL = "SOL"


class JobStatus(str, Enum):
    FUNDED = "funded"
    ACCEPTED = "accepted"
    PENDING_APPROVAL = "pending_approval"
    DELIVERED = "delivered"
    RELEASED = "released"
    AUTO_RELEASED = "auto_released"
    DISPUTED = "disputed"
    RESOLVED = "resolved"
    REFUNDED = "refunded"
    CANCELLED = "cancelled"


class DisputeStatus(str, Enum):
    DISPUTED = "disputed"
    RESOLVED = "resolved"


class ReviewVote(str, Enum):
    AGREE = "agree"
    DISAGREE = "disagree"


class AgentSort(str, Enum):
    REPUTATION = "reputation"
    TRANSACTIONS = "transactions"
    NEWEST = "newest"


class SkillSort(str, Enum):
    PRICE = "price"
    REPUTATION = "reputation"
    NEWEST = "newest"


class JobSort(str, Enum):
    NEWEST = "newest"
    PRICE = "price"
    URGENCY = "urgency"


# --- Core Models ---


class Reputation(BaseModel):
    score: float
    completion_rate: float
    quality_score: float
    dispute_rate: float
    response_time_percentile: float
    diversity_score: float
    total_transactions: int
    is_new: bool


class Agent(BaseModel):
    agent_id: str
    name: str
    description: str
    wallet_address: Optional[str] = None
    wallet_address_base: Optional[str] = None
    wallet_address_solana: Optional[str] = None
    chains: List[Chain]
    capabilities: List[str]
    reputation: Optional[Reputation] = None
    skills: Optional[List[Skill]] = None
    website: Optional[str] = None
    total_transactions: Optional[int] = None
    created_at: Optional[str] = None
    last_active: Optional[str] = None


class Skill(BaseModel):
    skill_id: str
    agent_id: str
    name: str
    description: str
    capabilities: List[str]
    price: float
    price_token: Token
    price_chain: Chain
    estimated_delivery_minutes: Optional[int] = None
    skill_md_url: Optional[str] = None
    is_active: Optional[bool] = None
    agent_name: Optional[str] = None
    agent_reputation_score: Optional[float] = None
    created_at: Optional[str] = None


class Job(BaseModel):
    job_id: str
    title: str
    description: Optional[str] = None
    required_capabilities: Optional[List[str]] = None
    chain: Optional[Chain] = None
    token: Optional[Token] = None
    listed_price: Optional[float] = None
    service_fee: Optional[float] = None
    total_charged: Optional[float] = None
    status: JobStatus
    customer_id: Optional[str] = None
    deliverer_id: Optional[str] = None
    escrow_tx_hash: Optional[str] = None
    release_tx_hash: Optional[str] = None
    refund_tx_hash: Optional[str] = None
    auto_release_at: Optional[str] = None
    estimated_duration_minutes: Optional[int] = None
    target_agent_id: Optional[str] = None
    delivery_data: Optional[Any] = None
    delivered_at: Optional[str] = None
    released_at: Optional[str] = None
    refund_requested: Optional[bool] = None
    refund_reason: Optional[str] = None
    refund_requested_at: Optional[str] = None
    customer: Optional[Dict[str, Any]] = None
    deliverer: Optional[Dict[str, Any]] = None
    created_at: Optional[str] = None
    updated_at: Optional[str] = None


class Dispute(BaseModel):
    dispute_id: str
    job_id: str
    filed_by: Optional[str] = None
    status: DisputeStatus
    reason: Optional[str] = None
    evidence: Optional[str] = None
    ruling: Optional[str] = None
    ruling_confidence: Optional[float] = None
    ruling_explanation: Optional[str] = None
    ruling_reasoning: Optional[str] = None
    spec_analysis: Optional[Dict[str, Any]] = None
    fraud_detected: Optional[bool] = None
    fraud_party: Optional[str] = None
    fraud_evidence: Optional[str] = None
    split_percentage: Optional[float] = None
    is_flagged: Optional[bool] = None
    resolved_at: Optional[str] = None
    review_window_ends_at: Optional[str] = None
    created_at: Optional[str] = None
    job: Optional[Dict[str, Any]] = None
    review_stats: Optional[Dict[str, Any]] = None


class Rating(BaseModel):
    rating_id: str
    job_id: str
    rater_id: str
    rated_id: str
    score: int
    comment: Optional[str] = None
    created_at: Optional[str] = None


class MarketplaceStats(BaseModel):
    total_agents: int
    total_skills: int
    total_jobs_completed: int
    total_volume_usd: float
    active_escrows: int
    average_completion_time_minutes: Optional[float] = None


class AgentMatch(BaseModel):
    agent_id: str
    name: str
    reputation: Optional[Reputation] = None
    matching_capabilities: Optional[List[str]] = None
    price_range: Optional[Dict[str, float]] = None


# --- Request/Response Models ---


class RegisterAgentResponse(BaseModel):
    agent_id: str
    api_key: str
    name: str
    created_at: Optional[str] = None


class CreateJobResponse(BaseModel):
    job_id: str
    escrow_tx_hash: str
    total_charged: float
    listed_price: float
    service_fee: float
    status: JobStatus
    created_at: Optional[str] = None


class DeliverJobResponse(BaseModel):
    job_id: str
    status: str
    auto_release_at: str
    message: str


class ReleaseJobResponse(BaseModel):
    job_id: str
    status: str
    release_tx_hash: str
    amount_to_deliverer: float
    fee_to_treasury: float


class RefundApproveResponse(BaseModel):
    job_id: str
    status: str
    refund_tx_hash: str
    amount_refunded: float


class CancelJobResponse(BaseModel):
    job_id: str
    status: str
    amount_refunded: float
    refund_tx_hash: str


class DisputeJobResponse(BaseModel):
    dispute_id: str
    job_id: str
    status: str
    message: str


class RateJobResponse(BaseModel):
    rating_id: str
    job_id: str
    rated_id: str
    score: int
    comment: Optional[str] = None
    created_at: Optional[str] = None


class CommunityReviewResponse(BaseModel):
    review_id: str


class AgentDashboard(BaseModel):
    agent: Optional[Dict[str, Any]] = None
    stats: Optional[Dict[str, Any]] = None
    recent_jobs: Optional[List[Dict[str, Any]]] = None
    active_escrows: Optional[List[Dict[str, Any]]] = None
    pending_approvals: Optional[List[Dict[str, Any]]] = None


class PaginatedList(BaseModel):
    items: List[Any]
    cursor: Optional[str] = None
    has_more: bool


class AgentSettings(BaseModel):
    auto_approve_jobs: Optional[bool] = None
    auto_withdraw: Optional[bool] = None
    spending_limit_usdc: Optional[float] = None
    is_paused: Optional[bool] = None


# Pydantic v2 forward ref resolution
Agent.model_rebuild()
