from __future__ import annotations

from decimal import Decimal
from typing import List, Optional
from uuid import UUID

from pydantic import BaseModel, Field, field_validator


class RecipeIngredientRef(BaseModel):
    ingredient_id: UUID
    qty: float = Field(gt=0)
    unit: Optional[str] = Field(default=None, max_length=50)
    notes: Optional[str] = None


class SideDishIngredient(BaseModel):
    name: str
    qty: float
    unit: Optional[str] = None


class SideDish(BaseModel):
    name: str
    ingredients: List[SideDishIngredient]
    prep_notes: Optional[str] = None


class RecipeBase(BaseModel):
    name: str = Field(min_length=1, max_length=300)
    description: Optional[str] = None
    image_url: Optional[str] = None
    prep_time_minutes: int = Field(ge=0)
    cook_time_minutes: int = Field(ge=0)
    servings: int = Field(gt=0)
    cuisine_tags: List[str] = Field(default_factory=list)
    dietary_tags: List[str] = Field(default_factory=list)
    protein_type: str = Field(min_length=1, max_length=50)
    spice_level: Optional[int] = Field(default=None, ge=0, le=5)
    calories_per_serving: Optional[int] = Field(default=None, ge=0)
    ingredients: List[RecipeIngredientRef] = Field(min_length=1)
    instructions: List[str] = Field(min_length=1)
    source_url: Optional[str] = None


class RecipeCreate(RecipeBase):
    pass


class RecipeUpdate(BaseModel):
    name: Optional[str] = None
    description: Optional[str] = None
    image_url: Optional[str] = None
    prep_time_minutes: Optional[int] = Field(default=None, ge=0)
    cook_time_minutes: Optional[int] = Field(default=None, ge=0)
    servings: Optional[int] = Field(default=None, gt=0)
    cuisine_tags: Optional[List[str]] = None
    dietary_tags: Optional[List[str]] = None
    protein_type: Optional[str] = None
    spice_level: Optional[int] = None
    calories_per_serving: Optional[int] = None
    ingredients: Optional[List[RecipeIngredientRef]] = None
    instructions: Optional[List[str]] = None
    side_dishes: Optional[List[SideDish]] = None


class RecipeRead(RecipeBase):
    id: UUID
    external_source: Optional[str] = None
    external_id: Optional[str] = None
    discovery_reason: Optional[str] = None
    side_dishes: List[SideDish] = Field(default_factory=list)

    model_config = {"from_attributes": True}


class ResolveIngredientRequest(BaseModel):
    text: str = Field(min_length=1)


class ResolveIngredientCandidate(BaseModel):
    ingredient_id: UUID
    name: str
    score: float
    aisle: Optional[str] = None


class ResolveIngredientResponse(BaseModel):
    parsed_qty: Optional[float] = None
    parsed_unit: Optional[str] = None
    parsed_text: str
    candidates: List[ResolveIngredientCandidate]
