from datetime import datetime, date
from typing import Optional, List

from fastapi import APIRouter, Query, Depends, Form, Path, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession

from src.database import get_db
from src.review.models import ReviewStatusEnum
from src.review.schemas import StoreReviewListResponse, SortField, SortOrder, StoreReviewResponse, \
    StoreReviewUpdateRequest, ManufacturerReviewListResponse, ManufacturerReviewResponse, ProductReviewListResponse, \
    ProductReviewResponse, ServiceReviewListResponse, ServiceReviewResponse
from src.review.service import ReviewService

router = APIRouter(prefix="/review", tags=["Review"])

@router.get("/store", response_model=StoreReviewListResponse)
async def get_reviews(
    needle: Optional[str] = Query(None, description="Текст для пошуку (по тексту відгуку, імені клієнта, телефону, назві магазину)"),
    date_start: Optional[str] = Query(None, description="Дата початку діапазону (YYYY-MM-DD)", example="2025-01-01"),
    date_end: Optional[str] = Query(None, description="Дата кінця діапазону (YYYY-MM-DD)", example="2025-01-31"),
    page: int = Query(1, ge=1, description="Номер сторінки для пагінації"),
    limit: int = Query(10, ge=1, description="Кількість відгуків на сторінку"),
    sort_field: str = Query("date_added", description="Поле сортування"),
    sort_order: str = Query("desc", description="Порядок сортування"),
    status: Optional[int] = Query(None, description="Фільтр по статусу (0=new, 1=approved, 2=rejected)"),
    store_id: Optional[int] = Query(None, description="Фільтр по ID магазину"),
    db: AsyncSession = Depends(get_db),
):
    date_range = None
    if date_start and date_end:
        date_range = [date_start, date_end]

    reviews, total, dashboard = await ReviewService.get_reviews(
        db=db,
        page=page,
        limit=limit,
        sort_field=sort_field,
        sort_order=sort_order,
        search=needle,
        status=status,
        store_id=store_id,
        date_range=date_range
    )

    reviews_pydantic = []
    for r in reviews:
        review_data = {
            "store_review_id": r.store_review_id,
            "store_id": r.store_id,
            "store_name": r.store.name if r.store else None,
            "date_added": r.date_added,
            "date_modify": r.date_modify,
            "status": r.status,
            "text": r.text,
            "rating": r.rating,
            "ip": r.ip,
            "customer": {
                "customer_id": r.customer.customer_id,
                "name": r.customer.name,
                "phone": r.customer.phone,
                "logo": r.customer.logo
            } if r.customer else None
        }
        reviews_pydantic.append(review_data)

    return {
        "data": reviews_pydantic,
        "dashboard": dashboard,
        "total": total,
        "page": page,
        "limit": limit,
        "status": True
    }

@router.patch("/store/{store_review_id}")
async def patch_store_review_status(
    store_review_id: int,
    status: int = Query(..., description="Статус відгуку (0 - new, 1 - approved, 2 - rejected)"),
    db: AsyncSession = Depends(get_db),
):
    if status not in [0, 1, 2]:
        raise HTTPException(status_code=400, detail="Invalid status value")
    status_enum = ReviewStatusEnum(status)
    updated_review = await ReviewService.update_store_review_status(db, store_review_id, status_enum)
    return {
        "data": updated_review,
        "status": True,
    }

@router.delete("/store/{store_review_id}")
async def delete_store_review(store_review_id: int, db: AsyncSession = Depends(get_db)):
    await ReviewService.delete_store_review(db, store_review_id)
    return {
        "data": "store_review deleted",
        "status": True
    }

@router.get("/manufacturer", response_model=ManufacturerReviewListResponse)
async def get_manufacturer_reviews(
    needle: Optional[str] = Query(None, description="Текст для пошуку (по тексту відгуку, імені клієнта, телефону, назві виробника)"),
    date_start: Optional[str] = Query(None, description="Дата початку діапазону (YYYY-MM-DD)", example="2025-01-01"),
    date_end: Optional[str] = Query(None, description="Дата кінця діапазону (YYYY-MM-DD)", example="2025-01-31"),
    page: int = Query(1, ge=1, description="Номер сторінки для пагінації (починається з 1)"),
    limit: int = Query(10, ge=1, description="Кількість відгуків на сторінку"),
    sort_field: str = Query("date_added", description="Поле для сортування ('date_added', 'rating' або 'manufacturer_review_id')"),
    sort_order: str = Query("desc", description="Порядок сортування ('asc' - за зростанням, 'desc' - за спаданням)"),
    status: Optional[int] = Query(None, description="Фільтр по статусу (0=new, 1=approved, 2=rejected)"),
    manufacturer_id: Optional[int] = Query(None, description="Фільтр по ID виробника"),
    db: AsyncSession = Depends(get_db),
):
    date_range = None
    if date_start and date_end:
        date_range = [date_start, date_end]

    reviews, total, dashboard = await ReviewService.get_manufacturer_reviews(
        db=db,
        page=page,
        limit=limit,
        sort_field=sort_field,
        sort_order=sort_order,
        search=needle,
        status=status,
        manufacturer_id=manufacturer_id,
        date_range=date_range
    )

    reviews_pydantic = []
    for r in reviews:
        review_data = {
            "manufacturer_review_id": r.manufacturer_review_id,
            "manufacturer_id": r.manufacturer_id,
            "manufacturer_name": r.manufacturer.name if r.manufacturer else None,
            "customer_id": r.customer_id,
            "text": r.text,
            "rating": r.rating,
            "status": r.status,
            "date_added": r.date_added,
            "date_modify": r.date_modify,
            "customer": {
                "customer_id": r.customer.customer_id,
                "name": r.customer.name,
                "phone": r.customer.phone,
                "logo": r.customer.logo
            } if r.customer else None,
        }
        reviews_pydantic.append(review_data)

    return {
        "data": reviews_pydantic,
        "dashboard": dashboard,
        "status": True,
        "total": total,
        "page": page,
        "limit": limit,
    }

@router.patch("/manufacturer/{manufacturer_review_id}")
async def patch_manufacturer_review_status(
        manufacturer_review_id: int,
        status: int = Query(..., description="Статус відгуку (0 - new, 1 - approved, 2 - rejected)"),
        db: AsyncSession = Depends(get_db),
):
    if status not in [0, 1, 2]:
        raise HTTPException(status_code=400, detail="Invalid status value")
    status_enum = ReviewStatusEnum(status)
    updated_review = await ReviewService.update_manufacturer_review_status(
        db, manufacturer_review_id, status_enum
    )
    return {
        "data": updated_review,
        "status": True,
    }

@router.delete("/manufacturer/{manufacturer_review_id}")
async def delete_manufacturer_review(
        manufacturer_review_id: int,
        db: AsyncSession = Depends(get_db)
):
    await ReviewService.delete_manufacturer_review(db, manufacturer_review_id)
    return {"data": "manufacturer review deleted",
            "status": True}

@router.get("/product", response_model=ProductReviewListResponse)
async def get_product_reviews(
    needle: Optional[str] = Query(None, description="Пошук по тексту відгуку, імені клієнта, телефону"),
    date_start: Optional[str] = Query(None, description="Дата початку діапазону (YYYY-MM-DD)", example="2025-01-01"),
    date_end: Optional[str] = Query(None, description="Дата кінця діапазону (YYYY-MM-DD)", example="2025-01-31"),
    status: Optional[int] = Query(None, description="Фільтрація за статусом: 0 - новий, 1 - підтверджений, 2 - відхилений"),
    manufacturer_id: Optional[int] = Query(None, description="ID виробника для фільтрації"),
    page: int = Query(1, ge=1, description="Номер сторінки"),
    limit: int = Query(10, ge=1, le=100, description="Кількість відгуків на сторінку"),
    sort_field: str = Query("date_added", regex="^(date_added|rating|product_review_id)$", description="Поле для сортування"),
    sort_order: str = Query("desc", regex="^(asc|desc)$", description="Порядок сортування"),
    db: AsyncSession = Depends(get_db),
):
    date_range = [date_start, date_end] if date_start and date_end else None

    reviews, total, dashboard = await ReviewService.get_product_reviews(
        db=db,
        search=needle,
        status=status,
        manufacturer_id=manufacturer_id,
        date_range=date_range,
        page=page,
        limit=limit,
        sort_field=sort_field,
        sort_order=sort_order,
    )

    reviews_pydantic = []
    for r in reviews:
        reviews_pydantic.append({
            "product_review_id": r.product_review_id,
            "product_id": r.product_id,
            "product_name": r.product.name if r.product else None,
            "manufacturer_id": r.manufacturer_id,
            "manufacturer_name": r.manufacturer.name if r.manufacturer else None,
            "customer_id": r.customer_id,
            "text": r.text,
            "rating": r.rating,
            "status": r.status,
            "ip": r.ip,
            "date_added": r.date_added,
            "date_modify": r.date_modify,
            "customer": r.customer
        })

    return {
        "data": reviews_pydantic,
        "dashboard": dashboard,
        "status": True,
        "total": total,
        "page": page,
        "limit": limit,
    }

@router.patch("/product/{product_review_id}")
async def patch_product_review_status(
        product_review_id: int,
        status: int = Query(..., description="Статус відгуку (0 - new, 1 - approved, 2 - rejected)"),
        db: AsyncSession = Depends(get_db),
):
    if status not in [0, 1, 2]:
        raise HTTPException(status_code=400, detail="Invalid status value")

    status_enum = ReviewStatusEnum(status)

    updated_review = await ReviewService.update_product_review_status(
        db, product_review_id, status_enum
    )
    return {
        "data": updated_review,
        "status": True,
    }

@router.delete("/product/{product_review_id}")
async def delete_product_review(
        product_review_id: int,
        db: AsyncSession = Depends(get_db),
):
    await ReviewService.delete_product_review(db, product_review_id)
    return {"data": "product review deleted",
            "status": True}

@router.get("/service", response_model=ServiceReviewListResponse)
async def get_service_reviews(
    db: AsyncSession = Depends(get_db),
    page: int = Query(1, ge=1, description="Номер сторінки"),
    limit: int = Query(10, ge=1, le=100, description="Кількість відгуків на сторінку"),
    needle: Optional[str] = Query(None, description="Пошук по тексту відгуку, імені клієнта, телефону"),
    status: Optional[int] = Query(None, description="Фільтрація за статусом (0 - new, 1 - approved, 2 - rejected)"),
    date_start: Optional[str] = Query(None, description="Дата початку діапазону (YYYY-MM-DD)", example="2025-01-01"),
    date_end: Optional[str] = Query(None, description="Дата кінця діапазону (YYYY-MM-DD)", example="2025-01-31"),
    sort_field: str = Query("date_added", pattern="^(date_added|rating|service_review_id)$", description="Поле для сортування"),
    sort_order: str = Query("desc", pattern="^(asc|desc)$", description="Порядок сортування"),
):
    date_range = None
    if date_start and date_end:
        date_range = [date_start, date_end]

    reviews, total, dashboard = await ReviewService.get_service_reviews(
        db=db,
        page=page,
        limit=limit,
        search=needle,
        status=status,
        date_range=date_range,
        sort_field=sort_field,
        sort_order=sort_order,
    )

    return {
        "data": [ServiceReviewResponse.model_validate(r) for r in reviews],
        "dashboard": dashboard,
        "status": True,
        "total": total,
        "page": page,
        "limit": limit,
    }

@router.patch("/service/{service_review_id}")
async def patch_service_review_status(
        service_review_id: int,
        status: int = Query(..., description="Статус відгуку (0 - new, 1 - approved, 2 - rejected)"),
        db: AsyncSession = Depends(get_db),
    ):
    if status not in [0, 1, 2]:
        raise HTTPException(status_code=400, detail="Invalid status value")

    status_enum = ReviewStatusEnum(status)

    updated_review = await ReviewService.update_service_review_service(
        db, service_review_id, status_enum
    )
    return {
        "data": updated_review,
        "status": True,
    }

@router.delete("/service/{service_review_id}")
async def delete_service_review(service_review_id: int, db: AsyncSession = Depends(get_db)):
    await ReviewService.delete_service_review(db, service_review_id)
    return {"data": "service review deleted",
            "status": True}