"""
Product schema definitions for common operations.
"""

from datetime import datetime
from typing import Optional, List, Union
from fastapi.params import Query
from pydantic import Field, ConfigDict, field_validator, model_validator, BaseModel
from src.apps.base.schemas.common import BaseSchema
from src.apps.files.schemas.file_common import FileResponseSchema
from src.core.utils.enums import ProductTypes



class ProductCategoryBase(BaseSchema):
    """Base product category schema."""
    
    name: str = Field(..., description="Category name")
    code: str = Field(..., max_length=255, description="Category code")
    slug: str = Field(..., description="Category slug")
    description: Optional[str] = Field(None, description="Category description")
    order: Optional[int] = Field(None, description="Category display order")
    is_active: bool = Field(True, description="Whether the category is active")
    parent_id: Optional[int] = Field(None, description="Parent category ID")


class ProductCategoryResponseSchema(ProductCategoryBase):
    """Product category response schema."""
    
    model_config = ConfigDict(from_attributes=True)
    
    id: int = Field(..., description="Category's unique identifier")
    merchant_id: Optional[int] = Field(None, description="Associated merchant ID")
    created_at: datetime = Field(..., description="When the category was created")
    updated_at: Optional[datetime] = Field(None, description="When the category was last updated")
    deleted_at: Optional[datetime] = Field(None, description="When the category was soft deleted")


class ProductBase(BaseSchema):
    """Base product schema with common fields."""
    
    name: str = Field(..., description="Product name")
    sku: str = Field(..., description="Product SKU (unique)")
    code: Optional[str] = Field(None, description="Product code")
    unit_price: float = Field(..., ge=0, description="Product unit price")
    sale_price: Optional[float] = Field(None, ge=0, description="Product sale price")
    description: Optional[str] = Field(None, description="Product description")
    is_active: bool = Field(True, description="Whether the product is active")
    is_new: bool = Field(False, description="Whether the product is marked as new")
    new_until: Optional[datetime] = Field(None, description="Date until product is considered new")
    item_type: str = Field("product", description="Item type: 'service' or 'product'")
    
    @field_validator('item_type', mode='before')
    @classmethod
    def validate_item_type(cls, v):
        """Validate and normalize item type to lowercase."""
        if isinstance(v, str):
            if v.lower() in ["service", "product"]:
                return v.lower()
            else:
                raise ValueError("Item type must be 'service' or 'product'")
        elif isinstance(v, ProductTypes):
            return "service" if v == ProductTypes.SERVICE else "product"
        else:
            raise ValueError("Item type must be 'service' or 'product'")
    
    @property
    def type_display(self) -> str:
        """Get human-readable item type display."""
        return self.item_type
    
    # Purchase related fields
    is_purchase: Optional[bool] = Field(False, description="Whether product is for purchase")
    purchase_msrp: Optional[float] = Field(None, ge=0, description="Purchase MSRP")
    purchase_manufacture_part_number: Optional[str] = Field(None, description="Purchase manufacture part number")
    purchase_supplier_sku: Optional[str] = Field(None, description="Purchase supplier SKU")
    purchase_description: Optional[str] = Field(None, description="Purchase description")
    calculated_purchase_tax_rate: float = Field(0.00, ge=0, description="Calculated purchase tax rate")
    
    # Sell related fields
    is_sell: Optional[bool] = Field(False, description="Whether product is for sell")
    sell_msrp: Optional[float] = Field(None, ge=0, description="Sell MSRP")
    sell_manufacture_part_number: Optional[str] = Field(None, description="Sell manufacture part number")
    sell_supplier_sku: Optional[str] = Field(None, description="Sell supplier SKU")
    sell_description: Optional[str] = Field(None, description="Sell description")
    calculated_sell_tax_rate: float = Field(0.00, ge=0, description="Calculated sell tax rate")
    
    # Physical dimensions
    length: Optional[float] = Field(None, ge=0, description="Product length")
    height: Optional[float] = Field(None, ge=0, description="Product height")
    width: Optional[float] = Field(None, ge=0, description="Product width")
    weight: Optional[float] = Field(None, ge=0, description="Product weight")
    depth: Optional[float] = Field(None, ge=0, description="Product depth")
    
    # Foreign keys
    category_id: int = Field(..., description="Product category ID")
    merchant_id: Optional[int] = Field(None, description="Associated merchant ID")


class ProductResponseSchema(ProductBase):
    """Product response schema."""
    
    model_config = ConfigDict(from_attributes=True)
    
    id: int = Field(..., description="Product's unique identifier")
    slug: str = Field(..., description="Product slug")
    item_type: str = Field(..., description="Item type: 'service' or 'product'")
    created_at: datetime = Field(..., description="When the product was created")
    updated_at: Optional[datetime] = Field(None, description="When the product was last updated")
    deleted_at: Optional[datetime] = Field(None, description="When the product was soft deleted")
    
    # Relationships
    category: Optional[ProductCategoryResponseSchema] = Field(None, description="Product category")
    thumbnail: Optional[FileResponseSchema] = Field(None, description="Product thumbnail image")
    product_attachments: Optional[List[FileResponseSchema]] = Field(None, description="Product attachment files")
    
    @property
    def type_display(self) -> str:
        """Get human-readable item type display."""
        return self.item_type


class ProductCreateSchema(ProductBase):
    """Schema for creating a new product."""
    
    # Required fields for creation
    name: str = Field(..., max_length=500, description="Product name (required)")
    sku: str = Field(..., max_length=500, description="Product SKU (required and unique)")
    attachments: Optional[List[int]] = Field(
        description="Uploaded file ids of optional attachments"
    )
    thumbnail: Optional[int] = Field(None, description="Thumbnail id of the attachment")


class ProductUpdateSchema(BaseSchema):
    """Schema for updating product information - all fields are optional for partial updates."""
    
    # Make all fields optional for updates
    name: Optional[str] = Field(None, max_length=500, description="Product name")
    sku: Optional[str] = Field(None, max_length=500, description="Product SKU")
    code: Optional[str] = Field(None, description="Product code")
    unit_price: Optional[float] = Field(None, ge=0, description="Product unit price")
    sale_price: Optional[float] = Field(None, ge=0, description="Product sale price")
    description: Optional[str] = Field(None, description="Product description")
    is_active: Optional[bool] = Field(None, description="Whether the product is active")
    is_new: Optional[bool] = Field(None, description="Whether the product is marked as new")
    new_until: Optional[datetime] = Field(None, description="Date until product is considered new")
    item_type: Optional[str] = Field(None, description="Item type: 'service' or 'product'")
    
    # Purchase related fields - optional for updates
    is_purchase: Optional[bool] = Field(None, description="Whether product is for purchase")
    purchase_msrp: Optional[float] = Field(None, ge=0, description="Purchase MSRP")
    purchase_manufacture_part_number: Optional[str] = Field(None, description="Purchase manufacture part number")
    purchase_supplier_sku: Optional[str] = Field(None, description="Purchase supplier SKU")
    purchase_description: Optional[str] = Field(None, description="Purchase description")
    calculated_purchase_tax_rate: Optional[float] = Field(None, ge=0, description="Calculated purchase tax rate")
    
    # Sell related fields - optional for updates
    is_sell: Optional[bool] = Field(None, description="Whether product is for sell")
    sell_msrp: Optional[float] = Field(None, ge=0, description="Sell MSRP")
    sell_manufacture_part_number: Optional[str] = Field(None, description="Sell manufacture part number")
    sell_supplier_sku: Optional[str] = Field(None, description="Sell supplier SKU")
    sell_description: Optional[str] = Field(None, description="Sell description")
    calculated_sell_tax_rate: Optional[float] = Field(None, ge=0, description="Calculated sell tax rate")
    
    # Physical dimensions - optional for updates
    length: Optional[float] = Field(None, ge=0, description="Product length")
    height: Optional[float] = Field(None, ge=0, description="Product height")
    width: Optional[float] = Field(None, ge=0, description="Product width")
    weight: Optional[float] = Field(None, ge=0, description="Product weight")
    depth: Optional[float] = Field(None, ge=0, description="Product depth")
    
    
    # Purchase related fields - optional for updates
    is_purchase: Optional[bool] = Field(None, description="Whether product is for purchase")
    purchase_msrp: Optional[float] = Field(None, ge=0, description="Purchase MSRP")
    purchase_manufacture_part_number: Optional[str] = Field(None, description="Purchase manufacture part number")
    purchase_supplier_sku: Optional[str] = Field(None, description="Purchase supplier SKU")
    purchase_description: Optional[str] = Field(None, description="Purchase description")
    calculated_purchase_tax_rate: Optional[float] = Field(None, ge=0, description="Calculated purchase tax rate")
    
    # Sell related fields - optional for updates
    is_sell: Optional[bool] = Field(None, description="Whether product is for sell")
    sell_msrp: Optional[float] = Field(None, ge=0, description="Sell MSRP")
    sell_manufacture_part_number: Optional[str] = Field(None, description="Sell manufacture part number")
    sell_supplier_sku: Optional[str] = Field(None, description="Sell supplier SKU")
    sell_description: Optional[str] = Field(None, description="Sell description")
    calculated_sell_tax_rate: Optional[float] = Field(None, ge=0, description="Calculated sell tax rate")
    
    # Physical dimensions - optional for updates
    length: Optional[float] = Field(None, ge=0, description="Product length")
    height: Optional[float] = Field(None, ge=0, description="Product height")
    width: Optional[float] = Field(None, ge=0, description="Product width")
    weight: Optional[float] = Field(None, ge=0, description="Product weight")
    depth: Optional[float] = Field(None, ge=0, description="Product depth")
    
    # Foreign keys - optional for updates
    category_id: Optional[int] = Field(None, description="Product category ID")
    merchant_id: Optional[int] = Field(None, description="Associated merchant ID")
    
    @field_validator('item_type', mode='before')
    @classmethod
    def validate_item_type(cls, v):
        """Validate and normalize item type to lowercase."""
        if v is None:
            return v
        if isinstance(v, str):
            if v.lower() in ["service", "product"]:
                return v.lower()
            else:
                raise ValueError("Item type must be 'service' or 'product'")
        elif isinstance(v, ProductTypes):
            return "service" if v == ProductTypes.SERVICE else "product"
        else:
            raise ValueError("Item type must be 'service' or 'product'")


class ProductListItemSchema(BaseSchema):
    """Simplified product schema for list views."""
    
    model_config = ConfigDict(from_attributes=True)
    
    id: int = Field(..., description="Product's unique identifier")
    name: str = Field(..., description="Product name")
    sku: str = Field(..., description="Product SKU")
    slug: str = Field(..., description="Product slug")
    unit_price: Optional[float] = Field(None, description="Product unit price")
    sale_price: Optional[float] = Field(None, description="Product sale price")
    is_active: bool = Field(..., description="Whether the product is active")
    is_new: bool = Field(..., description="Whether the product is marked as new")
    item_type: str = Field(..., description="Item type: 'service' or 'product'")
    category: Optional[ProductCategoryResponseSchema] = Field(None, description="Product category")
    thumbnail: Optional[FileResponseSchema] = Field(None, description="Product thumbnail image")
    created_at: datetime = Field(..., description="When the product was created")
    
    @property
    def type_display(self) -> str:
        """Get human-readable item type display."""
        return self.item_type


class ProductBulkDeleteSchema(BaseSchema):
    """Schema for bulk deleting products."""
    
    slugs: List[str] = Field(..., min_length=1, description="List of product slugs to delete")
    
    @field_validator('slugs')
    @classmethod
    def validate_slugs(cls, v):
        """Validate product slugs list."""
        if not v:
            raise ValueError("At least one product slug is required")
        if len(v) > 100:  # Reasonable limit for bulk operations
            raise ValueError("Cannot delete more than 100 products at once")
        return v


class ProductListFilterSchema(BaseModel):
    """Schema for filtering product list queries."""
    
    search: Optional[str] = Field(None, description="Search across name, sku, code, description")
    name: Optional[str] = Field(None, description="Filter by product name")
    sku: Optional[str] = Field(None, description="Filter by SKU")
    code: Optional[str] = Field(None, description="Filter by code")
    category_id: Optional[int] = Field(None, description="Filter by category ID")
    merchant_id: Optional[int] = Field(None, description="Filter by merchant ID")
    is_active: int = Field(0, description="Filter by active status (0=all, 1=active, -1=inactive)")
    is_new: int = Field(0, description="Filter by new status (0=all, 1=new, -1=not new)")
    is_purchase: int = Field(0, description="Filter by purchase status (0=all, 1=purchase, -1=not purchase)")
    is_sell: int = Field(0, description="Filter by sell status (0=all, 1=sell, -1=not sell)")
    item_type: Optional[str] = Field(None, description="Filter by item type: 'service' or 'product'")
    cost_price_range: Optional[str] = Query(default=None)
    
    @field_validator('item_type')
    @classmethod
    def validate_item_type(cls, v):
        """Validate item type filter."""
        if v is not None and v.lower() not in ['service', 'product']:
            raise ValueError("Item type must be 'service' or 'product'")
        return v.lower() if v else v
    
    @field_validator('is_active', 'is_new', 'is_purchase', 'is_sell')
    @classmethod
    def validate_boolean_filters(cls, v):
        """Validate boolean filter values."""
        if v not in [-1, 0, 1]:
            raise ValueError("Boolean filters must be -1 (false), 0 (all), or 1 (true)")
        return v
