"""
Pydantic Models for Mitai Jinkendo API

Data validation schemas for request/response bodies.
"""
from typing import Optional
from pydantic import BaseModel


# ── Profile Models ────────────────────────────────────────────────────────────

class ProfileCreate(BaseModel):
    name: str
    avatar_color: Optional[str] = '#1D9E75'
    sex: Optional[str] = 'm'
    dob: Optional[str] = None
    height: Optional[float] = 178
    goal_weight: Optional[float] = None
    goal_bf_pct: Optional[float] = None


class ProfileUpdate(BaseModel):
    name: Optional[str] = None
    avatar_color: Optional[str] = None
    sex: Optional[str] = None
    dob: Optional[str] = None
    height: Optional[float] = None
    goal_weight: Optional[float] = None
    goal_bf_pct: Optional[float] = None
    quality_filter_level: Optional[str] = None  # Issue #31: Global quality filter
    email: Optional[str] = None  # Self-service; leer = entfernen; Änderung setzt Verifikation zurück


# ── Tracking Models ───────────────────────────────────────────────────────────

class WeightEntry(BaseModel):
    date: str
    weight: float
    note: Optional[str] = None


class CircumferenceEntry(BaseModel):
    date: str
    c_neck: Optional[float] = None
    c_chest: Optional[float] = None
    c_waist: Optional[float] = None
    c_belly: Optional[float] = None
    c_hip: Optional[float] = None
    c_thigh: Optional[float] = None
    c_calf: Optional[float] = None
    c_arm: Optional[float] = None
    notes: Optional[str] = None
    photo_id: Optional[str] = None


class CaliperEntry(BaseModel):
    date: str
    sf_method: Optional[str] = 'jackson3'
    sf_chest: Optional[float] = None
    sf_axilla: Optional[float] = None
    sf_triceps: Optional[float] = None
    sf_subscap: Optional[float] = None
    sf_suprailiac: Optional[float] = None
    sf_abdomen: Optional[float] = None
    sf_thigh: Optional[float] = None
    sf_calf_med: Optional[float] = None
    sf_lowerback: Optional[float] = None
    sf_biceps: Optional[float] = None
    body_fat_pct: Optional[float] = None
    lean_mass: Optional[float] = None
    fat_mass: Optional[float] = None
    notes: Optional[str] = None


class ActivityEntry(BaseModel):
    date: str
    start_time: Optional[str] = None
    end_time: Optional[str] = None
    activity_type: str
    duration_min: Optional[float] = None
    kcal_active: Optional[float] = None
    kcal_resting: Optional[float] = None
    hr_avg: Optional[float] = None
    hr_max: Optional[float] = None
    distance_km: Optional[float] = None
    rpe: Optional[int] = None
    source: Optional[str] = 'manual'
    notes: Optional[str] = None
    training_type_id: Optional[int] = None        # v9d: Training type categorization
    training_category: Optional[str] = None       # v9d: Denormalized category
    training_subcategory: Optional[str] = None    # v9d: Denormalized subcategory


class NutritionDay(BaseModel):
    date: str
    kcal: Optional[float] = None
    protein_g: Optional[float] = None
    fat_g: Optional[float] = None
    carbs_g: Optional[float] = None


# ── Auth Models ───────────────────────────────────────────────────────────────

class LoginRequest(BaseModel):
    email: str
    password: str


class PasswordResetRequest(BaseModel):
    email: str


class PasswordResetConfirm(BaseModel):
    token: str
    new_password: str


class RegisterRequest(BaseModel):
    name: str
    email: str
    password: str


# ── Admin Models ──────────────────────────────────────────────────────────────

class AdminProfileUpdate(BaseModel):
    role: Optional[str] = None
    ai_enabled: Optional[int] = None
    ai_limit_day: Optional[int] = None
    export_enabled: Optional[int] = None


# ── Prompt Models (Issue #28) ────────────────────────────────────────────────

class PromptCreate(BaseModel):
    name: str
    slug: str
    display_name: Optional[str] = None
    description: Optional[str] = None
    template: str
    category: str = 'ganzheitlich'
    active: bool = True
    sort_order: int = 0


class PromptUpdate(BaseModel):
    name: Optional[str] = None
    display_name: Optional[str] = None
    description: Optional[str] = None
    template: Optional[str] = None
    category: Optional[str] = None
    active: Optional[bool] = None
    sort_order: Optional[int] = None


class PromptGenerateRequest(BaseModel):
    goal: str
    data_categories: list[str]
    example_output: Optional[str] = None


# ── Unified Prompt System Models (Issue #28 Phase 2) ───────────────────────

class StagePromptCreate(BaseModel):
    """Single prompt within a stage"""
    source: str  # 'inline' or 'reference'
    slug: Optional[str] = None  # Required if source='reference'
    template: Optional[str] = None  # Required if source='inline'
    output_key: str  # Key for storing result (e.g., 'nutrition', 'stage1_body')
    output_format: str = 'text'  # 'text' or 'json'
    output_schema: Optional[dict] = None  # JSON schema if output_format='json'


class StageCreate(BaseModel):
    """Single stage with multiple prompts"""
    stage: int  # Stage number (1, 2, 3, ...)
    prompts: list[StagePromptCreate]


class UnifiedPromptCreate(BaseModel):
    """Create a new unified prompt (base, pipeline, or workflow type)"""
    name: str
    slug: Optional[str] = None  # Auto-generated from name if not provided
    display_name: Optional[str] = None
    description: Optional[str] = None
    type: str  # 'base' | 'pipeline' | 'workflow'
    category: str = 'ganzheitlich'
    active: bool = True
    sort_order: int = 0

    # For base prompts (single reusable template)
    template: Optional[str] = None  # Required if type='base'
    output_format: str = 'text'
    output_schema: Optional[dict] = None

    # For pipeline prompts (multi-stage workflow)
    stages: Optional[list[StageCreate]] = None  # Required if type='pipeline'

    # For workflow prompts (visual graph editor)
    graph_data: Optional[dict] = None  # Required if type='workflow'


class UnifiedPromptUpdate(BaseModel):
    """Update an existing unified prompt"""
    name: Optional[str] = None
    display_name: Optional[str] = None
    description: Optional[str] = None
    type: Optional[str] = None
    category: Optional[str] = None
    active: Optional[bool] = None
    sort_order: Optional[int] = None
    template: Optional[str] = None
    output_format: Optional[str] = None
    output_schema: Optional[dict] = None
    stages: Optional[list[StageCreate]] = None
    graph_data: Optional[dict] = None  # For workflow type


# ── Pipeline Config Models (Issue #28) ─────────────────────────────────────
# NOTE: These will be deprecated in favor of UnifiedPrompt models above

class PipelineConfigCreate(BaseModel):
    name: str
    description: Optional[str] = None
    is_default: bool = False
    active: bool = True
    modules: dict  # {"körper": true, "ernährung": true, ...}
    timeframes: dict  # {"körper": 30, "ernährung": 30, ...}
    stage1_prompts: list[str]  # Array of slugs
    stage2_prompt: str  # slug
    stage3_prompt: Optional[str] = None  # slug


class PipelineConfigUpdate(BaseModel):
    name: Optional[str] = None
    description: Optional[str] = None
    is_default: Optional[bool] = None
    active: Optional[bool] = None
    modules: Optional[dict] = None
    timeframes: Optional[dict] = None
    stage1_prompts: Optional[list[str]] = None
    stage2_prompt: Optional[str] = None
    stage3_prompt: Optional[str] = None


class PipelineExecuteRequest(BaseModel):
    config_id: Optional[str] = None  # None = use default config
