from __future__ import annotations from datetime import datetime from typing import Any from uuid import UUID from pydantic import BaseModel, Field, field_validator class RecipeImportListItem(BaseModel): id: UUID source: str external_id: str source_url: str source_revision: str name: str | None status: str acquired_at: datetime reviewed_at: datetime | None reviewed_by: str | None recipe_id: UUID | None class RecipeImportListResponse(BaseModel): items: list[RecipeImportListItem] total: int limit: int offset: int has_next: bool class RecipeImportDetail(BaseModel): id: UUID source: str external_id: str source_url: str source_revision: str license_name: str license_url: str attribution: str raw_payload: dict[str, Any] payload_sha256: str normalized_recipe: dict[str, Any] validation_report: dict[str, Any] status: str rejection_reason: str | None recipe_id: UUID | None acquired_at: datetime reviewed_at: datetime | None reviewed_by: str | None model_config = {"from_attributes": True} class RecipeImportRejectRequest(BaseModel): reason: str = Field(min_length=1, max_length=1000) @field_validator("reason") @classmethod def normalize_reason(cls, value: str) -> str: cleaned = value.strip() if not cleaned: raise ValueError("reason must not be blank") return cleaned