from __future__ import annotations

from typing import Any, Literal

from pydantic import BaseModel, Field, model_validator


class ProfileUpdate(BaseModel):
    display_name: str | None = None
    height_inches: float | None = Field(default=None, gt=0)
    goal_weight_lbs: float | None = Field(default=None, gt=0)
    measurement_system: Literal['imperial'] | None = 'imperial'
    notes: str | None = None


class WeightEntryCreate(BaseModel):
    recorded_at: str
    weight_lbs: float = Field(gt=0)
    body_fat_percent: float | None = Field(default=None, ge=0, le=100)
    notes: str | None = None


class MeasurementEntryCreate(BaseModel):
    recorded_at: str
    waist_inches: float | None = Field(default=None, gt=0)
    hip_inches: float | None = Field(default=None, gt=0)
    chest_inches: float | None = Field(default=None, gt=0)
    neck_inches: float | None = Field(default=None, gt=0)
    notes: str | None = None

    @model_validator(mode='after')
    def validate_at_least_one_measurement(self) -> 'MeasurementEntryCreate':
        if not any(
            value is not None
            for value in [self.waist_inches, self.hip_inches, self.chest_inches, self.neck_inches]
        ):
            raise ValueError('At least one body measurement is required.')
        return self


class ExerciseTemplateCreate(BaseModel):
    name: str
    primary_muscle: str | None = None
    equipment: str | None = None
    notes: str | None = None


class RoutineExerciseCreate(BaseModel):
    exercise_name: str
    target_sets: int = Field(ge=1)
    target_reps: str
    notes: str | None = None


class RoutineCreate(BaseModel):
    user_id: str
    name: str
    notes: str | None = None
    exercises: list[RoutineExerciseCreate]


class WorkoutSetCreate(BaseModel):
    reps: int = Field(ge=1)
    weight_lbs: float = Field(ge=0)
    rpe: float | None = Field(default=None, ge=0)
    rest_seconds: int | None = Field(default=None, ge=0)
    notes: str | None = None


class WorkoutExerciseCreate(BaseModel):
    exercise_name: str
    notes: str | None = None
    sets: list[WorkoutSetCreate]


class WorkoutCreate(BaseModel):
    user_id: str
    performed_at: str
    routine_name: str
    notes: str | None = None
    exercises: list[WorkoutExerciseCreate]


JSONDict = dict[str, Any]
