"""Pydantic models for Armory SDK."""

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

from pydantic import BaseModel, Field


class Project(BaseModel):
    """Project model."""

    id: str
    name: str
    description: str = ""
    created_at: Optional[str] = None
    updated_at: Optional[str] = None


class Run(BaseModel):
    """Run model (W&B-compatible)."""

    id: str
    project_id: str = Field(alias="project_id")

    # W&B compatible fields
    name: str = ""
    group: str = ""  # Optional grouping (replaces experiment_id)
    tags: List[str] = Field(default_factory=list)
    notes: str = ""

    # Run classification
    model_type: str = Field(default="embedding", alias="model_type")
    run_type: str = Field(default="training", alias="run_type")
    status: str = "pending"

    # Training context
    goal: str = ""
    base_model: str = Field(default="", alias="base_model")
    dataset_path: str = Field(default="", alias="dataset_path")

    # W&B compatible: config (hyperparameters)
    config: Dict[str, Any] = Field(default_factory=dict)

    # W&B compatible: metrics and summary
    metrics: Dict[str, float] = Field(default_factory=dict)
    summary: Dict[str, Any] = Field(default_factory=dict)
    error: str = ""

    # Timestamps
    created_at: Optional[str] = Field(default=None, alias="created_at")
    started_at: Optional[str] = Field(default=None, alias="started_at")
    completed_at: Optional[str] = Field(default=None, alias="completed_at")

    class Config:
        populate_by_name = True


# Alias for backwards compatibility
Session = Run


class TriggerCondition(BaseModel):
    """Trigger condition for skills."""

    type: str
    pattern: Optional[str] = None
    metric: Optional[str] = None
    condition: Optional[str] = None
    threshold: Optional[float] = None
    intents: List[str] = Field(default_factory=list)
    confidence: float = 0.0


class HyperparameterSpec(BaseModel):
    """Hyperparameter specification."""

    default: Any
    range: Optional[List[Any]] = None
    recommended: Optional[Any] = None
    description: str = ""


class SkillDependencies(BaseModel):
    """Skill dependencies."""

    skills: List[str] = Field(default_factory=list)
    packages: List[str] = Field(default_factory=list)
    tools: List[str] = Field(default_factory=list)


class ReferenceFile(BaseModel):
    """Reference file in a skill."""

    name: str
    path: str
    file_type: str = Field(default="reference", alias="fileType")
    content_type: str = Field(default="text", alias="contentType")
    content: str = ""
    executable: bool = False
    description: str = ""

    class Config:
        populate_by_name = True


class Skill(BaseModel):
    """Skill model."""

    id: str = ""
    project_id: str = Field(default="", alias="projectId")
    model_type: str = Field(default="", alias="modelType")
    name: str
    description: str = ""
    content: str = ""
    version: int = 1
    trigger_conditions: List[TriggerCondition] = Field(
        default_factory=list, alias="triggerConditions"
    )
    dependencies: Optional[SkillDependencies] = None
    reference_files: List[ReferenceFile] = Field(
        default_factory=list, alias="referenceFiles"
    )
    hyperparameters: Dict[str, HyperparameterSpec] = Field(default_factory=dict)
    usage_count: int = Field(default=0, alias="usageCount")
    success_rate: float = Field(default=0.0, alias="successRate")
    avg_improvement: float = Field(default=0.0, alias="avgImprovement")
    source_session_id: str = Field(default="", alias="sourceSessionId")
    author: str = ""
    tags: List[str] = Field(default_factory=list)
    metadata: Dict[str, str] = Field(default_factory=dict)
    # Agent Skills compatibility
    allowed_tools: List[str] = Field(default_factory=list, alias="allowedTools")
    license: str = ""
    compatibility: str = ""
    activation_mode: str = Field(default="implicit", alias="activationMode")
    created_at: Optional[str] = Field(default=None, alias="createdAt")
    updated_at: Optional[str] = Field(default=None, alias="updatedAt")

    class Config:
        populate_by_name = True


class FailedAttempt(BaseModel):
    """Failed attempt (anti-pattern) model."""

    id: str = ""
    project_id: str = Field(default="", alias="projectId")
    model_type: str = Field(default="", alias="modelType")
    approach: str
    reason: str
    context: str = ""
    suggestion: str = ""
    severity: str = "medium"
    category: str = "training"
    error_type: str = Field(default="", alias="errorType")
    error_log: str = Field(default="", alias="errorLog")
    code_snippet: str = Field(default="", alias="codeSnippet")
    failed_hyperparameters: Dict[str, Any] = Field(
        default_factory=dict, alias="failedHyperparameters"
    )
    session_id: str = Field(default="", alias="sessionId")
    experiment_id: str = Field(default="", alias="experimentId")
    tags: List[str] = Field(default_factory=list)
    metadata: Dict[str, str] = Field(default_factory=dict)

    class Config:
        populate_by_name = True


# =========================================================================
# Request/Response models for Agentic API
# =========================================================================


class AdviseRequest(BaseModel):
    """Request for /advise endpoint."""

    goal: str
    project_id: Optional[str] = Field(default=None, alias="projectId")
    model_type: Optional[str] = Field(default=None, alias="modelType")
    context: Dict[str, Any] = Field(default_factory=dict)

    class Config:
        populate_by_name = True


class AdviseResponse(BaseModel):
    """Response from /advise endpoint."""

    recommendations: List[str] = Field(default_factory=list)
    relevant_skills: List[Skill] = Field(default_factory=list, alias="relevantSkills")
    warnings: List[str] = Field(default_factory=list)
    suggested_hyperparameters: Dict[str, Any] = Field(
        default_factory=dict, alias="suggestedHyperparameters"
    )

    class Config:
        populate_by_name = True


class RetrospectiveRequest(BaseModel):
    """Request for /retrospective endpoint."""

    session_id: str = Field(alias="sessionId")
    outcome: str  # "success", "partial", "failure"
    metrics: Dict[str, float]
    error_log: Optional[str] = Field(default=None, alias="errorLog")
    hyperparameters: Optional[Dict[str, Any]] = None
    observations: Optional[str] = None
    auto_create_skill: bool = Field(default=True, alias="autoCreateSkill")

    class Config:
        populate_by_name = True


class RetrospectiveResponse(BaseModel):
    """Response from /retrospective endpoint."""

    summary: str
    learnings: List[str] = Field(default_factory=list)
    skill_created: bool = Field(default=False, alias="skillCreated")
    skill_id: Optional[str] = Field(default=None, alias="skillId")
    failed_attempt_created: bool = Field(default=False, alias="failedAttemptCreated")
    failed_attempt_id: Optional[str] = Field(default=None, alias="failedAttemptId")

    class Config:
        populate_by_name = True
