import json
from datetime import datetime
from enum import Enum
from typing import List, Optional, TypedDict

from fastapi import Form
from pydantic import BaseModel, Field, ConfigDict

from src.product.models import ProductStatus


class ProductOut(BaseModel):
    product_id: int
    name: str
    status: int = ProductStatus
    category: Optional[str] = None
    price: float
    price_old: Optional[float] = None
    image: Optional[str] = None

class ProductDashboard(BaseModel):
    total_quantity: int
    quantity_on: int
    quantity_off: int

class ProductListResponse(BaseModel):
    data: List[ProductOut]
    dashboard: ProductDashboard
    page: int
    limit: int
    total: int
    status: bool

class CategoryBrief(BaseModel):
    category_id: int
    name: str

class AttributeOut(BaseModel):
    group_name: str
    name: str
    value: str
    sort_order: int

class ImageOut(BaseModel):
    image: str
    sort_order: int

class StoreOut(BaseModel):
    store_id: int
    name: str

class ManufacturerOut(BaseModel):
    manufacturer_id: int
    name: str

class ProductDetailResponse(BaseModel):
    product_id: int
    name: str
    description: Optional[str]
    seo_keyword: Optional[str]
    meta_title: Optional[str]
    meta_description: Optional[str]
    meta_keyword: Optional[str]
    image: Optional[str]
    status: int
    date_added: datetime
    date_modify: datetime
    price: float
    price_old: Optional[float] = None
    model: Optional[str]
    rating: float
    viewed: int
    categories: List[CategoryBrief]
    attributes: List[AttributeOut]
    images: List[ImageOut]
    stores: List[StoreOut]
    manufacturer: Optional[ManufacturerOut]

class ProductDetailWrapper(BaseModel):
    data: ProductDetailResponse
    status: bool

class CategoryIn(BaseModel):
    category_id: int



class ImageIn(BaseModel):
    image: str
    sort_order: Optional[int] = 0

class ProductStatusEnum(str, Enum):
    OFF = "OFF"
    ON = "ON"

class ProductCreate(BaseModel):
    name: str = Field(..., max_length=255)
    description: Optional[str] = None
    price: float = Field(None, ge=0)
    model: Optional[str] = None
    manufacturer_id: Optional[int] = None
    seo_keyword: Optional[str] = None
    meta_title: Optional[str] = None
    meta_description: Optional[str] = None
    meta_keyword: Optional[str] = None

class ProductResponse(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    product_id: int
    name: str
    description: Optional[str]
    price: float
    price_old: Optional[float] = None
    model: Optional[str]
    manufacturer_id: Optional[int]
    status: ProductStatus
    seo_keyword: Optional[str]
    meta_title: Optional[str]
    meta_description: Optional[str]
    meta_keyword: Optional[str]
    image: Optional[str]
    date_added: datetime
    date_modify: datetime

    @staticmethod
    def format_datetime(dt: datetime) -> str:
        return dt.strftime("%Y-%m-%d %H:%M:%S") if dt else None

    @classmethod
    def from_orm(cls, obj):
        data = super().from_orm(obj).dict()
        data["date_added"] = cls.format_datetime(obj.date_added)
        data["date_modify"] = cls.format_datetime(obj.date_modify)
        return cls(**data)

class ProductUpdate(BaseModel):
    name: Optional[str] = Field(None, max_length=255)
    description: Optional[str] = None
    price: Optional[float] = Field(None, ge=0)
    model: Optional[str] = None
    manufacturer_id: Optional[int] = None
    status: Optional[ProductStatusEnum] = None
    seo_keyword: Optional[str] = None
    meta_title: Optional[str] = None
    meta_description: Optional[str] = None
    meta_keyword: Optional[str] = None

class ProductImageResponse(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    product_image_id: int
    image: str
    sort_order: int

class ProductImageResponseWrapper(BaseModel):
    model_config = ConfigDict(from_attributes=True)
    data: ProductImageResponse
    status: bool

class CategoryResponse(BaseModel):
    category_id: int
    name: str

    class Config:
        from_attributes = True

class ProductCategoryResponse(BaseModel):
    product_category_id: int
    product_id: int
    category_id: int

    class Config:
        from_attributes = True

class ProductCategoryCreate(BaseModel):
    category_id: int

class ProductCategoryResponseWrapper(BaseModel):
    data: ProductCategoryResponse
    status: bool

class ProductAttributeResponse(BaseModel):
    product_attribute_id: int
    product_id: int
    group_name: str
    name: str
    value: str
    sort_order: int

    class Config:
        from_attributes = True

class ProductAttributeResponseWrapperList(BaseModel):
    data: List[ProductAttributeResponse]
    status: bool
    page: int
    limit: int
    total: int

class ProductAttributeResponseWrapper(BaseModel):
    data: ProductAttributeResponse
    status: bool

class ProductAttributeCreate(BaseModel):
    group_name: str = Field(..., example="Specifications")
    name: str = Field(..., example="Weight")
    value: str = Field(..., example="1.5kg")
    sort_order: int = Field(0, example=0)

class ProductAttributeResponseWrapperCreate(BaseModel):
    data: ProductAttributeResponse
    status: bool

class ProductAttributeUpdate(BaseModel):
    group_name: Optional[str] = Field(None, example="Specifications")
    name: Optional[str] = Field(None, example="Weight")
    value: Optional[str] = Field(None, example="1.5kg")
    sort_order: Optional[int] = Field(None, example=0)

class TransferProductsRequest(BaseModel):
    product_ids: List[int]
    old_category_id: Optional[int] = None
    new_category_id: int

class TransferResult(TypedDict):
    transferred_count: int
    new_links_created: int
    old_category_id: Optional[int]
    new_category_id: int

# Filter Group Schemas
class FilterGroupCreate(BaseModel):
    name: Optional[str] = Field(None, max_length=255)
    sort_order: int = Field(0)

class FilterCreate(BaseModel):
    name: Optional[str] = Field(None, max_length=255)
    filter_group_id: int = Field(0)
    sort_order: int = Field(0)

class FilterGroupUpdate(BaseModel):
    name: Optional[str] = Field(None, max_length=255)
    sort_order: Optional[int] = Field(None)

class FilterGroupResponse(BaseModel):
    filter_group_id: int
    name: str
    sort_order: int
    
    class Config:
        from_attributes = True

class FilterGroupResponseWrapper(BaseModel):
    data: FilterGroupResponse
    status: bool


class ProductImagesFromUrlsRequest(BaseModel):
    urls: List[str]