from __future__ import annotations

import json
from datetime import datetime
from typing import Any, Optional

from pydantic import BaseModel, ConfigDict, HttpUrl, field_validator


class ProductBase(BaseModel):
    boutique: str
    url: HttpUrl
    asin: str
    titre: Optional[str]
    url_image: Optional[HttpUrl]
    categorie: Optional[str]
    type: Optional[str]
    actif: Optional[bool] = True


class ProductCreate(ProductBase):
    pass


class ProductUpdate(BaseModel):
    titre: Optional[str] = None
    url_image: Optional[HttpUrl] = None
    categorie: Optional[str] = None
    type: Optional[str] = None
    actif: Optional[bool] = None


class ProductRead(ProductBase):
    model_config = ConfigDict(from_attributes=True)

    id: int
    cree_le: datetime
    modifie_le: datetime


class ProductSnapshotBase(BaseModel):
    prix_actuel: Optional[float]
    prix_conseille: Optional[float]
    prix_min_30j: Optional[float]
    etat_stock: Optional[str]
    en_stock: Optional[bool]
    note: Optional[float]
    nombre_avis: Optional[int]
    prime: Optional[bool]
    choix_amazon: Optional[bool]
    offre_limitee: Optional[bool]
    exclusivite_amazon: Optional[bool]
    # Données étendues
    a_propos: Optional[list[str]] = None
    description: Optional[str] = None
    carateristique: Optional[dict[str, Any]] = None
    details: Optional[dict[str, Any]] = None
    categorie_amazon: Optional[str] = None
    statut_scrap: Optional[str]
    message_erreur: Optional[str]


class ProductSnapshotRead(ProductSnapshotBase):
    model_config = ConfigDict(from_attributes=True)

    id: int
    produit_id: int
    scrape_le: datetime

    @field_validator("a_propos", mode="before")
    @classmethod
    def parse_a_propos(cls, v: Any) -> list[str] | None:
        if v is None:
            return None
        if isinstance(v, str):
            try:
                return json.loads(v)
            except json.JSONDecodeError:
                return None
        return v

    @field_validator("carateristique", "details", mode="before")
    @classmethod
    def parse_json_dict(cls, v: Any) -> dict[str, Any] | None:
        if v is None:
            return None
        if isinstance(v, str):
            try:
                return json.loads(v)
            except json.JSONDecodeError:
                return None
        return v


class ProductWithSnapshot(ProductBase):
    """Produit enrichi avec les données du dernier snapshot."""

    model_config = ConfigDict(from_attributes=True)

    id: int
    cree_le: datetime
    modifie_le: datetime
    # Données du dernier snapshot
    prix_actuel: Optional[float] = None
    prix_conseille: Optional[float] = None
    prix_min_30j: Optional[float] = None
    reduction_pourcent: Optional[int] = None
    etat_stock: Optional[str] = None
    en_stock: Optional[bool] = None
    note: Optional[float] = None
    nombre_avis: Optional[int] = None
    prime: Optional[bool] = None
    choix_amazon: Optional[bool] = None
    offre_limitee: Optional[bool] = None
    exclusivite_amazon: Optional[bool] = None
    # Données étendues
    a_propos: Optional[list[str]] = None
    description: Optional[str] = None
    carateristique: Optional[dict[str, Any]] = None
    details: Optional[dict[str, Any]] = None
    categorie_amazon: Optional[str] = None
    dernier_scrape: Optional[datetime] = None
    statut_scrap: Optional[str] = None


class ProductCreateWithSnapshot(ProductBase):
    """Création d'un produit avec données de snapshot initiales (depuis preview)."""

    # Données du snapshot initial
    prix_actuel: Optional[float] = None
    prix_conseille: Optional[float] = None
    prix_min_30j: Optional[float] = None
    etat_stock: Optional[str] = None
    en_stock: Optional[bool] = None
    note: Optional[float] = None
    nombre_avis: Optional[int] = None
    prime: Optional[bool] = None
    choix_amazon: Optional[bool] = None
    offre_limitee: Optional[bool] = None
    exclusivite_amazon: Optional[bool] = None
    # Données étendues
    a_propos: Optional[list[str]] = None
    description: Optional[str] = None
    carateristique: Optional[dict[str, Any]] = None
    details: Optional[dict[str, Any]] = None
    categorie_amazon: Optional[str] = None
