from fastapi import APIRouter, Depends, HTTPException, status, UploadFile, File
from fastapi.responses import FileResponse
from sqlalchemy.orm import Session, joinedload
from typing import List, Optional
from pathlib import Path
from app.database.database import get_db
from app.models import Product, Category, User
from app.schemas.product import (
    ProductCreate,
    ProductResponse,
    ProductUpdate,
)
from app.services.product import (
    get_products,
    get_product_by_id,
    create_product,
    update_product,
    delete_product,
    search_products,
)
from app.services.auth import get_current_admin_user
from app.utils import save_upload_file, generate_slug
from app.config import settings

router = APIRouter(prefix="/api/products", tags=["products"])


@router.get("", response_model=List[ProductResponse])
def list_products(
    category_id: Optional[int] = None,
    model_id: Optional[int] = None,
    brand: Optional[str] = None,
    gender: Optional[str] = None,
    min_price: Optional[float] = None,
    max_price: Optional[float] = None,
    on_sale: Optional[bool] = None,
    featured: Optional[bool] = None,
    skip: int = 0,
    limit: int = 20,
    db: Session = Depends(get_db),
):
    query = db.query(Product).options(joinedload(Product.model))
    
    if category_id:
        query = query.filter(Product.category_id == category_id)
    if model_id:
        query = query.filter(Product.model_id == model_id)
    if brand:
        query = query.filter(Product.brand.ilike(f"%{brand}%"))
    if gender:
        query = query.filter(Product.gender == gender)
    if min_price is not None:
        query = query.filter(Product.price >= min_price)
    if max_price is not None:
        query = query.filter(Product.price <= max_price)
    if on_sale is not None:
        query = query.filter(Product.is_on_sale == on_sale)
    if featured is not None:
        query = query.filter(Product.is_featured == featured)
    
    products = query.offset(skip).limit(limit).all()
    
    # Inherit sizes and price from model if product doesn't have them
    for product in products:
        if (not product.sizes or len(product.sizes) == 0) and product.model_id and product.model:
            product.sizes = product.model.sizes or []
        # Inherit price from model if not set
        if product.price is None and product.model_id and product.model and product.model.base_price:
            product.price = float(product.model.base_price)
    
    return products


@router.get("/search", response_model=List[ProductResponse])
def search(q: str, skip: int = 0, limit: int = 20, db: Session = Depends(get_db)):
    products = search_products(db, q, skip=skip, limit=limit)
    
    # Inherit sizes and price from model if product doesn't have them
    for product in products:
        if (not product.sizes or len(product.sizes) == 0) and product.model_id and product.model:
            product.sizes = product.model.sizes or []
        # Inherit price from model if not set
        if product.price is None and product.model_id and product.model and product.model.base_price:
            product.price = float(product.model.base_price)
    
    return products


@router.get("/{product_id}", response_model=ProductResponse)
def get_product(product_id: int, db: Session = Depends(get_db)):
    product = get_product_by_id(db, product_id)
    if not product:
        raise HTTPException(status_code=404, detail="Product not found")
    
    # If product doesn't have sizes but has a model, inherit sizes from model
    if (not product.sizes or len(product.sizes) == 0) and product.model_id and product.model:
        product.sizes = product.model.sizes or []
    # Inherit price from model if not set
    if product.price is None and product.model_id and product.model and product.model.base_price:
        product.price = float(product.model.base_price)
    
    return product


@router.post("", response_model=ProductResponse)
def create_new_product(
    product: ProductCreate,
    db: Session = Depends(get_db),
    admin: User = Depends(get_current_admin_user),
):
    # Validate price: either product has price OR model has base_price
    if product.price is None:
        if not product.model_id:
            raise HTTPException(
                status_code=400,
                detail="Price is required when no model is assigned"
            )
        # Check if model exists and has base_price
        from app.models import Model
        model = db.query(Model).filter(Model.id == product.model_id).first()
        if not model:
            raise HTTPException(status_code=404, detail="Model not found")
        if model.base_price is None:
            raise HTTPException(
                status_code=400,
                detail="Model must have a base_price set if product price is not provided"
            )
    
    # Auto-generate slug if not provided
    if not product.slug:
        base_slug = generate_slug(f"{product.brand} {product.name}")
        # Check if slug exists and make it unique
        slug = base_slug
        counter = 1
        while db.query(Product).filter(Product.slug == slug).first():
            slug = f"{base_slug}-{counter}"
            counter += 1
        product.slug = slug
    
    created_product = create_product(db, product)
    
    # Refresh to get the model relationship
    db.refresh(created_product)
    
    # Inherit price and sizes from model if needed
    if created_product.price is None and created_product.model_id and created_product.model:
        created_product.price = float(created_product.model.base_price)
    if (not created_product.sizes or len(created_product.sizes) == 0) and created_product.model_id and created_product.model:
        created_product.sizes = created_product.model.sizes or []
    
    return created_product


@router.put("/{product_id}", response_model=ProductResponse)
def update_existing_product(
    product_id: int,
    product_update: ProductUpdate,
    db: Session = Depends(get_db),
    admin: User = Depends(get_current_admin_user),
):
    product = update_product(db, product_id, product_update)
    if not product:
        raise HTTPException(status_code=404, detail="Product not found")
    
    # Refresh to ensure model relationship is loaded
    db.refresh(product)
    
    # Inherit price and sizes from model if needed
    if product.price is None and product.model_id and product.model and product.model.base_price:
        product.price = float(product.model.base_price)
    if (not product.sizes or len(product.sizes) == 0) and product.model_id and product.model:
        product.sizes = product.model.sizes or []
    
    return product


@router.delete("/{product_id}")
def delete_existing_product(
    product_id: int,
    db: Session = Depends(get_db),
    admin: User = Depends(get_current_admin_user),
):
    if not delete_product(db, product_id):
        raise HTTPException(status_code=404, detail="Product not found")
    return {"message": "Product deleted successfully"}


@router.post("/upload-image")
async def upload_product_image(
    file: UploadFile = File(...),
    admin: User = Depends(get_current_admin_user),
):
    """Upload a product image and return the URL"""
    # Validate file type
    allowed_types = ["image/jpeg", "image/png", "image/jpg", "image/webp", "image/gif"]
    if file.content_type not in allowed_types:
        raise HTTPException(
            status_code=400,
            detail=f"File type {file.content_type} not allowed. Allowed types: {', '.join(allowed_types)}"
        )
    
    try:
        # Save file and get path
        file_path = save_upload_file(file, folder="products", backend_url=settings.backend_url)
        # Return full URL
        return {"url": file_path, "message": "Image uploaded successfully"}
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Error uploading file: {str(e)}")


@router.post("/upload-images")
async def upload_multiple_images(
    files: List[UploadFile] = File(...),
    admin: User = Depends(get_current_admin_user),
):
    """Upload multiple product images and return the URLs"""
    allowed_types = ["image/jpeg", "image/png", "image/jpg", "image/webp", "image/gif"]
    uploaded_urls = []
    errors = []
    
    for file in files:
        if file.content_type not in allowed_types:
            errors.append(f"File {file.filename}: type {file.content_type} not allowed")
            continue
        
        try:
            file_path = save_upload_file(file, folder="products", backend_url=settings.backend_url)
            uploaded_urls.append(file_path)
        except Exception as e:
            errors.append(f"File {file.filename}: {str(e)}")
    
    return {
        "urls": uploaded_urls,
        "uploaded_count": len(uploaded_urls),
        "errors": errors if errors else None,
        "message": f"Successfully uploaded {len(uploaded_urls)} of {len(files)} images"
    }


@router.get("/filters/brands")
def get_brands(db: Session = Depends(get_db)):
    """Get list of unique brands from products"""
    brands = db.query(Product.brand).distinct().filter(Product.brand.isnot(None)).all()
    return [brand[0] for brand in brands if brand[0]]


@router.get("/filters/sizes")
def get_sizes(db: Session = Depends(get_db)):
    """Get list of unique sizes from products"""
    products = db.query(Product.sizes).filter(Product.sizes.isnot(None)).all()
    sizes_set = set()
    for product in products:
        if product.sizes:
            for size in product.sizes:
                sizes_set.add(size)
    return sorted(list(sizes_set))
