import asyncio
import json
import re
from datetime import datetime
from typing import Optional, List

from fastapi import APIRouter, Query, Depends, Path, UploadFile, File, HTTPException, Form, Body, BackgroundTasks
from sqlalchemy import select, delete
from sqlalchemy.ext.asyncio import AsyncSession
from starlette import status

from src.category.models import Category
from src.database import get_db
from src.product.models import ProductStatus, ProductImage, ProductAttribute, ProductCategory, Product
from src.product.schemas import ProductListResponse, ProductDetailWrapper, ProductCreate, ProductResponse, \
    ProductUpdate, ProductImageResponse, ProductStatusEnum, ProductImageResponseWrapper, CategoryResponse, \
    ProductCategoryResponse, ProductCategoryCreate, ProductCategoryResponseWrapper, ProductAttributeResponse, \
    ProductAttributeResponseWrapper, ProductAttributeCreate, ProductAttributeResponseWrapperCreate, \
    ProductAttributeUpdate, ProductAttributeResponseWrapperList, TransferProductsRequest, \
    FilterGroupCreate, FilterGroupUpdate, FilterGroupResponse, FilterGroupResponseWrapper, FilterCreate, \
    ProductImagesFromUrlsRequest
from src.product.service import ProductService
from src.store.models import ProductStore
from src.store.schemas import AddStoreToProductRequest, ProductStoreUpdate
from src.utils.image_manager import handle_image_upload
from src.cache.download_cache import update_product_cache
from src.seo.service import SeoService
from src.utils.product_logger import log_product_create, log_product_update, log_product_delete

router = APIRouter(prefix="/product", tags=["Product"])

@router.post("/clean-duplicate-attributes")
async def clean_duplicate_attributes_endpoint(
    background_tasks: BackgroundTasks,
    db: AsyncSession = Depends(get_db)
):
    """
    Запускає фоновий процес для очищення дублікатів характеристик у всіх товарах.
    """
    background_tasks.add_task(ProductService.clean_duplicate_attributes, db)
    return {"message": "Cleaning process started in the background. Check the server console for progress."}


@router.get("", response_model=ProductListResponse)
async def list_products(
    needle: Optional[str] = Query(None, description="Пошук по назві продукту"),
    category_id: Optional[int] = Query(None, description="Category ID"),
    price_min: Optional[float] = Query(None, ge=0, description="Ціна від"),
    price_max: Optional[float] = Query(None, ge=0, description="Ціна до"),
    status: Optional[int] = Query(None, ge=0, le=1, description="Статус продукту: 0=OFF, 1=ON"),
    sort_field: Optional[str] = Query("name", regex="^(name|price|category|date_added|product_id)$", description="Поле сортування"),
    sort_order: Optional[str] = Query("asc", regex="^(asc|desc|ASC|DESC)$", description="Напрям сортування"),
    page: int = Query(1, ge=1, description="Номер сторінки"),
    limit: int = Query(10, ge=1, description="Кількість на сторінці"),
    db: AsyncSession = Depends(get_db),
):
    return await ProductService.get_products(
        db=db,
        needle=needle,
        category_id=category_id,
        price_min=price_min,
        price_max=price_max,
        status=status,
        sort_field=sort_field,
        sort_order=sort_order.lower() if sort_order else "asc",  # Нормалізуємо до lowercase
        page=page,
        limit=limit,
    )

@router.get("/{product_id}", response_model=ProductDetailWrapper)
async def get_product_detail(
    product_id: int = Path(..., description="ID товару"),
    db: AsyncSession = Depends(get_db)
):
    product = await ProductService.get_product_by_id(product_id, db)
    return {
        "data": product,
        "status": True
    }


@router.post("")
async def create_product(
    name: str = Form(..., max_length=255),
    description: Optional[str] = Form(None),
    price: float = Form(None, ge=0),
    price_old: float = Form(None, ge=0),
    model: Optional[str] = Form(None),
    manufacturer_id: Optional[int] = Form(None),
    seo_keyword: Optional[str] = Form(None),
    meta_title: Optional[str] = Form(None),
    meta_description: Optional[str] = Form(None),
    meta_keyword: Optional[str] = Form(None),
    image: Optional[UploadFile] = File(None),
    original_image_url: Optional[str] = Form(None),
    db: AsyncSession = Depends(get_db)
):
    # 1. Обробляємо картинку
    # image_url = await handle_image_upload(image)
    image_url = original_image_url

    # 2. Створюємо продукт
    product_data = {
        "name": name,
        "description": description,
        "price": price,
        "price_old": price_old,
        "model": model,
        "manufacturer_id": manufacturer_id,
        "seo_keyword": seo_keyword,
        "meta_title": meta_title,
        "meta_description": meta_description,
        "meta_keyword": meta_keyword,
        "image_url": image_url
    }
    product = await ProductService.create_product(product_data, db)

    # 3. Логуємо створення продукту
    log_product_create(
        product_id=product.product_id,
        data=product_data,
        image_filename=image.filename if image else None
    )

    await SeoService.generate_seo_product(product.product_id, db)

    # 4. Оновлюємо кеш в фоновому режимі
    asyncio.create_task(update_product_cache(product.product_id))

    # 5. Повертаємо відповідь
    return {
        "data": ProductResponse.from_orm(product),
        "status": True
    }

@router.patch("/{product_id}")
async def patch_product(
    product_id: int,
    name: Optional[str] = Form(None, max_length=255),
    description: Optional[str] = Form(None),
    price: Optional[float] = Form(None, ge=0),
    price_old: Optional[float] = Form(None, ge=0),
    model: Optional[str] = Form(None),
    manufacturer_id: Optional[int] = Form(None),
    status: Optional[int] = Form(None),
    seo_keyword: Optional[str] = Form(None),
    meta_title: Optional[str] = Form(None),
    meta_description: Optional[str] = Form(None),
    meta_keyword: Optional[str] = Form(None),
    image: Optional[UploadFile] = File(None),
    db: AsyncSession = Depends(get_db)
):
    update_data = {
        "name": name,
        "description": description,
        "price": price,
        "price_old": price_old,
        "model": model,
        "manufacturer_id": manufacturer_id,
        "status": status,
        "seo_keyword": seo_keyword,
        "meta_title": meta_title,
        "meta_description": meta_description,
        "meta_keyword": meta_keyword,
    }

    product = await ProductService.update_product(
        product_id=product_id,
        data=update_data,
        image_file=image,
        db=db,
    )

    # Логуємо оновлення продукту
    log_product_update(
        product_id=product_id,
        data=update_data,
        image_filename=image.filename if image else None
    )

    # Оновлюємо кеш в фоновому режимі
    asyncio.create_task(update_product_cache(product_id))

    return {
        "data": ProductResponse.from_orm(product),
        "status": True
    }

@router.delete("/{product_id}")
async def delete_product(
        product_id: int,
        db: AsyncSession = Depends(get_db)
):
    await ProductService.delete_product(product_id, db)

    # Логуємо видалення продукту
    log_product_delete(product_id=product_id)

    asyncio.create_task(update_product_cache(product_id))
    return {
        "data": "product deleted successfully",
        "status": True
    }

@router.get("/{product_id}/image")
async def get_product_images(
    product_id: int = Path(...),
    page: int = Query(1, ge=1, description="Page number"),
    limit: int = Query(10, ge=1, le=100, description="Items per page"),
    db: AsyncSession = Depends(get_db)
):
    images, total = await ProductService.get_product_images(product_id, db, page, limit)
    return {
        "data": [ProductImageResponse.from_orm(img) for img in images],
        "status": True,
        "page": page,
        "limit": limit,
        "total": total,
    }

@router.get("/{product_id/image/{product_image_id}")
async def get_product_image(
        product_id: int,
        product_image_id: int,
        db: AsyncSession = Depends(get_db)
):
    image = await ProductService.get_product_image(product_id, product_image_id, db)
    return {
        "data": ProductImageResponse.from_orm(image),
        "status": True,
    }

@router.post("/{product_id}/image")
async def add_product_images(
        product_id: int,
        file: List[UploadFile],
        db: AsyncSession = Depends(get_db)
):
    images = await ProductService.add_product_images(product_id, file, db)

    asyncio.create_task(update_product_cache(product_id))
    return {
        "data": [ProductImageResponse.from_orm(image) for image in images],
        "status": True
    }

@router.post("/{product_id}/image/url")
async def add_product_images_from_urls(
        product_id: int,
        body: ProductImagesFromUrlsRequest,
        db: AsyncSession = Depends(get_db)
):
    images = await ProductService.add_product_images_from_urls(product_id, body.urls, db)

    asyncio.create_task(update_product_cache(product_id))
    return {
        "data": [ProductImageResponse.from_orm(image) for image in images],
        "status": True
    }


@router.patch("/{product_id}/image/{product_image_id}", response_model=ProductImageResponseWrapper)
async def update_product_image_sort_order(
        product_id: int = Path(...),
        product_image_id: int = Path(...),
        sort_order: int = Body(..., embed=True),
        db: AsyncSession = Depends(get_db)
):
    product_image = await ProductService.update_product_image_sort_order(
        product_id=product_id,
        product_image_id=product_image_id,
        sort_order=sort_order,
        db=db
    )

    asyncio.create_task(update_product_cache(product_id))
    return ProductImageResponseWrapper(
        data=ProductImageResponse.from_orm(product_image),
        status=True
    )

@router.delete("/{product_id}/image/{product_image_id}")
async def delete_product_image(
        product_id: int,
        product_image_id: int,
        db: AsyncSession = Depends(get_db)
):
    asyncio.create_task(update_product_cache(product_id))
    await ProductService.delete_product_image(product_id, product_image_id, db)
    return {
        "data": "product image deleted successfully",
        "status": True
    }

@router.get("/{product_id}/category")
async def get_product_categories(
    product_id: int = Path(...),
    page: int = Query(1, ge=1, description="Page number"),
    limit: int = Query(10, ge=1, le=100, description="Items per page"),
    db: AsyncSession = Depends(get_db),
):
    categories, total = await ProductService.get_product_category_with_path(product_id, db, page, limit)

    asyncio.create_task(update_product_cache(product_id))
    return {
        "data": categories,
        "status": True,
        "page": page,
        "limit": limit,
        "total": total,
    }


@router.get("/{product_id}/category/{product_category_id}")
async def get_product_category(
    product_id: int = Path(...),
    product_category_id: int = Path(...),
    db: AsyncSession = Depends(get_db)
):
    category = await ProductService.get_product_category(product_id, product_category_id, db)
    return {
        "data": CategoryResponse.from_orm(category),
        "status": True
    }

@router.post("/{product_id}/category", response_model=ProductCategoryResponseWrapper)
async def add_category_to_product(
        product_id: int = Path(...),
        body: ProductCategoryCreate  = Body(...),
        db: AsyncSession = Depends(get_db)
):
    product_category = await ProductService.add_category_to_product(product_id, body.category_id, db)

    asyncio.create_task(update_product_cache(product_id))
    return {
        "data": product_category,
        "status": True
    }

@router.delete("/{product_id}/category/{product_category_id}", status_code=status.HTTP_200_OK)
async def delete_product_category(
        product_id: int = Path(...),
        product_category_id: int = Path(...),
        db: AsyncSession = Depends(get_db)
):
    await ProductService.delete_product_category(product_id, product_category_id, db)

    asyncio.create_task(update_product_cache(product_id))
    return {
        "data": "product category deleted successfully",
        "status": True
    }

@router.get("/{product_id}/attribute", response_model=ProductAttributeResponseWrapperList)
async def get_product_attributes(
    product_id: int = Path(...),
    needle: Optional[str] = Query(None, description="Пошук по group_name, name або value"),
    page: int = Query(1, ge=1, description="Page number"),
    limit: int = Query(10, ge=1, le=100, description="Items per page"),
    db: AsyncSession = Depends(get_db)
):
    attributes, total = await ProductService.get_product_attributes(product_id, db, page, limit, needle)
    return {
        "data": attributes,
        "status": True,
        "page": page,
        "limit": limit,
        "total": total,
    }

@router.get("/{product_id}/attribute/{product_attribute_id}", response_model=ProductAttributeResponseWrapper)
async def get_product_attribute(
        product_id: int = Path(...),
        product_attribute_id: int = Path(...),
        db: AsyncSession = Depends(get_db)
):
    attribute = await ProductService.get_product_attribute(product_id, product_attribute_id, db)
    return {
        "data": attribute,
        "status": True
    }

@router.post("/{product_id}/attribute", response_model=ProductAttributeResponseWrapperCreate, status_code=status.HTTP_201_CREATED)
async def add_product_attribute(
        product_id: int = Path(...),
        data: ProductAttributeCreate = Body(...),
        db: AsyncSession = Depends(get_db)
):
    attribute = await ProductService.add_product_attribute(product_id, data, db)

    asyncio.create_task(update_product_cache(product_id))

    return {
        "data": attribute,
        "status": True
    }

@router.patch("/{product_id}/attribute/{product_attribute_id}", response_model=ProductAttributeResponseWrapper)
async def update_product_attribute(
        product_id: int = Path(...),
        product_attribute_id: int = Path(...),
        data: ProductAttributeUpdate = Body(...),
        db: AsyncSession = Depends(get_db)
):
    attribute = await ProductService.update_product_attribute(product_id, product_attribute_id, data, db)

    asyncio.create_task(update_product_cache(product_id))

    return {
        "data": attribute,
        "status": True
    }

@router.delete("/{product_id}/attribute/{product_attribute_id}")
async def delete_product_attribute(
        product_id: int = Path(...),
        product_attribute_id: int = Path(...),
        db: AsyncSession = Depends(get_db)
):
    await ProductService.delete_product_attribute(product_id, product_attribute_id, db)

    asyncio.create_task(update_product_cache(product_id))

    return {
        "data": "product attribute deleted successfully",
        "status": True
    }

@router.get("/{product_id}/store")
async def get_product_stores(
    product_id: int = Path(...),
    page: int = Query(1, ge=1, description="Page number"),
    limit: int = Query(10, ge=1, le=100, description="Items per page"),
    needle: str | None = Query(None, description="Search by store name"),
    db: AsyncSession = Depends(get_db),
):
    stores, total = await ProductService.get_product_stores(product_id, db, page, limit, needle)
    return {
        "data": stores,
        "status": True,
        "page": page,
        "limit": limit,
        "total": total
    }

@router.get("/{product_id}/store/{product_store_id}")
async def get_product_store(
        product_id: int = Path(...),
        product_store_id: int = Path(...),
        db: AsyncSession = Depends(get_db)
):
    store = await ProductService.get_product_store(product_id, product_store_id, db)
    return {
        "data": store,
        "status": True
    }

@router.post("/{product_id}/store", status_code=status.HTTP_201_CREATED)
async def add_store_to_product(
        product_id: int = Path(...),
        data: AddStoreToProductRequest = Body(...),
        db: AsyncSession = Depends(get_db)
):
    try:
        product_store = await ProductService.add_store_to_product(
            product_id=product_id,
            store_id=data.store_id,
            price=data.price,
            price_old=data.price_old,
            db=db
        )

        asyncio.create_task(update_product_cache(product_id))

        return {
            "data": {
                "product_store_id": product_store.product_store_id,
                "product_id": product_store.product_id,
                "store_id": product_store.store_id,
                "price": product_store.price,
                "price_old": product_store.price_old,
                "date_added": product_store.date_added.isoformat() if product_store.date_added else None,
                "date_modify": product_store.date_modify.isoformat() if product_store.date_modify else None,
            },
            "status": True
        }
    except Exception as e:
        # Логуємо деталі помилки
        import traceback
        print(f"Error in add_store_to_product: {str(e)}")
        print(f"Traceback: {traceback.format_exc()}")
        raise HTTPException(status_code=500, detail=str(e))


@router.patch("/{product_id}/store/{store_id}")
async def update_product_store(
        product_id: int = Path(...),
        store_id: int = Path(...),
        data: ProductStoreUpdate = Body(...),
        db: AsyncSession = Depends(get_db)
):
    update_data = {k: v for k, v in data.model_dump().items() if v is not None}
    if not update_data:
        raise HTTPException(status_code=400, detail="No fields to update")

    product_store = await ProductService.update_product_store(
        product_id=product_id,
        store_id=store_id,
        update_data=update_data,
        db=db
    )

    asyncio.create_task(update_product_cache(product_id))

    return {
        "data": {
            "product_store_id": product_store.product_store_id,
            "product_id": product_store.product_id,
            "store_id": product_store.store_id,
            "price": product_store.price,
            "price_old": product_store.price_old,
            "date_added": product_store.date_added.isoformat() if product_store.date_added else None,
            "date_modify": product_store.date_modify.isoformat() if product_store.date_modify else None,
        },
        "status": True
    }


@router.post("/transfer-category")
async def transfer_products_between_categories(
        request: TransferProductsRequest,
        db: AsyncSession = Depends(get_db)
):
    """
    Перенести товари з однієї категорії в іншу
    """
    try:
        result = await ProductService.transfer_products_to_new_category(
            request.product_ids,
            request.old_category_id,
            request.new_category_id,
            db
        )

        return {
            "status": True,
            "message": f"Перенесено {result['transferred_count']} товарів до категорії {result['new_category_id']}",
            "transferred_products": request.product_ids,
            **result
        }

    except ValueError as e:
        raise HTTPException(status_code=404, detail=str(e))
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.get("/filter_group")
async def get_filter_groups(
    page: int = Query(1, ge=1, description="Сторінка"),
    limit: int = Query(10, ge=1, le=100, description="На сторінці"),
    needle: str | None = Query(None, description="Пошук"),
    db: AsyncSession = Depends(get_db)
):
    return await ProductService.get_filter_group_list(db=db, needle=needle, page=page, limit=limit)
@router.get("/filter_group/{filter_group_id}")
async def get_filter_group(
    filter_group_id: int,
    db: AsyncSession = Depends(get_db)
):
    return await ProductService.get_filter_group(db=db, filter_group_id=filter_group_id)

@router.post("/filter_group", response_model=FilterGroupResponseWrapper)
async def create_filter_group(
    data: FilterGroupCreate,
    db: AsyncSession = Depends(get_db)
):
    return await ProductService.add_filter_group(db=db, name=data.name, sort_order=data.sort_order)

@router.patch("/filter_group/{filter_group_id}", response_model=FilterGroupResponseWrapper)
async def update_filter_group(
    filter_group_id: int,
    data: FilterGroupUpdate,
    db: AsyncSession = Depends(get_db)
):
    return await ProductService.update_filter_group(
        db=db, 
        filter_group_id=filter_group_id, 
        name=data.name, 
        sort_order=data.sort_order
    )

@router.delete("/filter_group/{filter_group_id}")
async def delete_filter_group(
    filter_group_id: int,
    db: AsyncSession = Depends(get_db)
):
    return await ProductService.delete_filter_group(db=db, filter_group_id=filter_group_id)

@router.get("/filter")
async def get_filters(
    page: int = Query(1, ge=1, description="Сторінка"),
    limit: int = Query(10, ge=1, le=100, description="На сторінці"),
    filter_group_id: int = Query(None, description="Група фільтрів"),
    needle: str | None = Query(None, description="Пошук"),
    db: AsyncSession = Depends(get_db)
):
    return await ProductService.get_filter_list(db=db, needle=needle, filter_group_id=filter_group_id, page=page, limit=limit)
@router.get("/filter/{filter_id}")
async def get_filter(
    filter_id: int,
    db: AsyncSession = Depends(get_db)
):
    return await ProductService.get_filter(db=db, filter_id=filter_id)

@router.post("/filter")
async def create_filter(
    data: FilterCreate,
    db: AsyncSession = Depends(get_db)
):
    return await ProductService.add_filter(db=db, name=data.name, sort_order=data.sort_order, filter_group_id=data.filter_group_id)

@router.patch("/filter/{filter_id}")
async def update_filter(
    filter_id: int,
    data: FilterGroupUpdate,
    db: AsyncSession = Depends(get_db)
):
    return await ProductService.update_filter(
        db=db,
        filter_id=filter_id,
        name=data.name,
        sort_order=data.sort_order
    )

@router.delete("/filter/{filter_id}")
async def delete_filter(
    filter_id: int,
    db: AsyncSession = Depends(get_db)
):
    return await ProductService.delete_filter(db=db, filter_id=filter_id)

@router.get("/product/{product_id}/filter")
async def get_product_filters(
        product_id: int,
        needle: Optional[str] = Query(None, description="Пошук по назві фільтра або групи"),
        page: int = Query(1, ge=1, description="Номер сторінки"),
        limit: int = Query(10, ge=1, le=1000, description="Кількість на сторінці"),
        db: AsyncSession = Depends(get_db)
):
    return await ProductService.get_product_filters(db=db, product_id=product_id, needle=needle, page=page, limit=limit)

@router.get("/product/{product_id}/filter/{filter_id}")
async def get_product_filter(
    product_filter_id: int,
    db: AsyncSession = Depends(get_db)
):
    return await ProductService.get_product_filter(db=db, product_filter_id=product_filter_id)

@router.post("/product/{product_id}/filter")
async def add_product_filter(
    product_id: int,
    filter_id: int,
    db: AsyncSession = Depends(get_db)
):
    return await ProductService.add_product_filter(db=db, product_id=product_id, filter_id=filter_id)

@router.delete("/product/{product_id}/filter/{filter_id}")
async def remove_product_filter(
    product_id: int,
    filter_id: int,
    db: AsyncSession = Depends(get_db)
):
    return await ProductService.delete_product_filter(db=db, product_id=product_id, filter_id=filter_id)

@router.post("/generate-filters-from-attributes")
async def generate_filters_from_attributes(
    db: AsyncSession = Depends(get_db)
):
    """
    Генерирует фильтры из всех характеристик товаров и автоматически привязывает их к товарам.
    ProductAttribute.name → название группы фильтров
    ProductAttribute.value → название фильтра
    """
    return await ProductService.generate_and_assign_filters_from_attributes(db=db)

@router.get("/category/{category_id}/export")
async def export(
    category_id: int,
    db: AsyncSession = Depends(get_db)
):

    return await ProductService.export_product(category_id, db=db)