from typing import Optional

from fastapi import APIRouter, Query, Depends, HTTPException, Form, UploadFile, File, Path, Body, Response
from pydantic import EmailStr, ValidationError, parse_obj_as
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from src.database import get_db
from src.product.models import Product
from src.store.models import StoreStatus, ProductStore, Store
from src.store.schemas import StoreCreate, StoreUpdate, StoreResponse, StorePhotoResponse, StoreAddressCreate, \
    StoreAddressResponse, StoreAddressUpdate, StoreAddressFilter, StoreListResponse, ProductStoreCreate, ProductStoreOut
from src.store.service import StoreService
from src.utils.image_manager import handle_image_upload

router = APIRouter(prefix="/store", tags=["store"])


@router.get("", response_model=StoreListResponse)
async def list_stores(
        needle: Optional[str] = Query(None, description="Пошук по назві магазину"),
        sort_field: str = Query(
            "date_added",
            alias="sort[field]",
            regex="^(name|date_added|id|rating)$",
            description="Поле сортування магазину (name, date_added, id, rating)"
        ),
        sort_order: str = Query(
            "DESC",
            alias="sort[order]",
            regex="^(ASC|DESC|asc|desc)$",
            description="Напрям сортування: ASC/asc=зростання, DESC/desc=спадання"
        ),
        page: int = Query(1, ge=1, description="Номер сторінки"),
        limit: int = Query(10, ge=1, description="Кількість на сторінці"),
        db: AsyncSession = Depends(get_db),
):
    try:
        result = await StoreService.get_stores_list(
            db=db,
            needle=needle,
            sort_field=sort_field,
            sort_order=sort_order,
            page=page,
            limit=limit,
        )
        return {
            "data": result["items"],
            "total": result["total"],
            "page": page,
            "limit": limit,
            "status": True,
        }
    except Exception as e:
        return {
            "data": [],
            "status": False,
            "message": str(e),
            "total": 0,
            "page": page,
            "limit": limit,
        }


@router.get("/{store_id}")
async def get_store_by_id(
        store_id: int,
        db: AsyncSession = Depends(get_db)
):
    try:
        store = await StoreService.get_store_by_id(db=db, store_id=store_id)
        return {
            "data": store,
            "status": True,
        }
    except HTTPException as e:
        return {
            "data": None,
            "status": False,
            "message": e.detail,
        }
    except Exception as e:
        return {
            "data": None,
            "status": False,
            "message": str(e),
        }


@router.post("", status_code=201)
async def create_store(
        name: str = Form(...),
        description: Optional[str] = Form(None),
        address: Optional[str] = Form(None),
        phone: Optional[str] = Form(None),
        seo_keyword: Optional[str] = Form(None),
        email: Optional[str] = Form(None),
        website: Optional[str] = Form(None),
        # Social media URLs
        url_youtube: Optional[str] = Form(None),
        url_viber: Optional[str] = Form(None),
        url_facebook: Optional[str] = Form(None),
        url_telegram: Optional[str] = Form(None),

        status: Optional[int] = Form(StoreStatus.OFF.value),
        meta_title: Optional[str] = Form(None),
        meta_description: Optional[str] = Form(None),
        meta_keyword: Optional[str] = Form(None),
        logo: Optional[UploadFile] = File(None),
        db: AsyncSession = Depends(get_db),
):
    if status not in [0, 1]:
        raise HTTPException(status_code=400, detail="Invalid status value, used only 0 or 1")

    email_validated = None
    if email is not None:
        try:
            email_validated = parse_obj_as(EmailStr, email)
        except ValidationError:
            raise HTTPException(status_code=400, detail="Invalid email address")

    data = StoreCreate(
        name=name,
        description=description,
        address=address,
        phone=phone,
        email=email_validated,
        website=website,
        url_youtube=url_youtube,
        url_viber=url_viber,
        url_facebook=url_facebook,
        url_telegram=url_telegram,
        status=status,
        seo_keyword=seo_keyword,
        meta_title=meta_title,
        meta_description=meta_description,
        meta_keyword=meta_keyword,
    )
    logo_url = await handle_image_upload(logo) if logo else "/assets/placeholder.webp"

    try:
        new_store = await StoreService.create_store(db=db, data=data, logo_url=logo_url)
        return {
            "data": new_store,
            "status": True
        }
    except Exception as e:
        return {"data": None, "status": False, "message": str(e)}


@router.patch("/{store_id}", status_code=200)
async def update_store(
        store_id: int,
        name: Optional[str] = Form(None),
        description: Optional[str] = Form(None),
        address: Optional[str] = Form(None),
        phone: Optional[str] = Form(None),
        email: Optional[EmailStr] = Form(None),
        website: Optional[str] = Form(None),
        # Social media URLs
        url_youtube: Optional[str] = Form(None),
        url_viber: Optional[str] = Form(None),
        url_facebook: Optional[str] = Form(None),
        url_telegram: Optional[str] = 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),
        logo: Optional[UploadFile] = File(None),
        db: AsyncSession = Depends(get_db),
):
    if status is not None:
        if status not in [0, 1]:
            raise HTTPException(status_code=400, detail="Invalid status value, used only 0 or 1")

    update_data = {
        "name": name,
        "description": description,
        "address": address,
        "phone": phone,
        "email": email,
        "website": website,
        "url_youtube": url_youtube,
        "url_viber": url_viber,
        "url_facebook": url_facebook,
        "url_telegram": url_telegram,
        "status": status,
        "seo_keyword": seo_keyword,
        "meta_title": meta_title,
        "meta_description": meta_description,
        "meta_keyword": meta_keyword,
    }
    update_data = {k: v for k, v in update_data.items() if v is not None}

    logo_url = None
    if logo is not None:
        logo_url = await handle_image_upload(logo)

    try:
        updated_store = await StoreService.update_store(
            db=db,
            store_id=store_id,
            update_data=update_data,
            logo_url=logo_url
        )
        return {"data": updated_store, "status": True}
    except HTTPException as http_exc:
        raise http_exc
    except Exception as e:
        return {
            "data": None,
            "status": False,
            "message": str(e)
        }


@router.delete("/{store_id}", status_code=204)
async def delete_store(
        store_id: int,
        db: AsyncSession = Depends(get_db)
):
    await StoreService.delete_store(db=db, store_id=store_id)
    return None


@router.get("/{store_id}/photo")
async def get_store_photo(
        store_id: int = Path(..., description="Store ID"),
        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)
):
    photos, total = await StoreService.get_store_photos(store_id=store_id, db=db, page=page, limit=limit)
    return {
        "data": [StorePhotoResponse.model_validate(photo) for photo in photos],
        "status": True,
        "page": page,
        "limit": limit,
        "total": total,
    }


@router.post("/{store_id}/photo", status_code=201)
async def upload_store_photo(
        store_id: int = Path(..., description="ID магазину"),
        file: UploadFile = File(..., description="Фото магазину"),
        db: AsyncSession = Depends(get_db)
):
    try:
        image_url = await handle_image_upload(file)

        photo = await StoreService.add_store_photo(
            db=db,
            store_id=store_id,
            image_url=image_url
        )
        return {
            "data": StorePhotoResponse.model_validate(photo),
            "status": True
        }
    except HTTPException as http_exc:
        raise http_exc
    except Exception as e:
        return {
            "data": None,
            "status": False,
            "message": str(e)
        }


@router.delete("/{store_id}/photo/{store_photo_id}")
async def delete_store_photo(
        store_id: int = Path(..., description="Store ID"),
        store_photo_id: int = Path(..., description="Store Photo ID"),
        db: AsyncSession = Depends(get_db)
):
    try:
        await StoreService.delete_store_photo(
            db=db,
            store_id=store_id,
            store_photo_id=store_photo_id
        )
        return {"data": "Store photo deleted", "status": True}
    except HTTPException as http_exc:
        raise http_exc
    except Exception as e:
        return {
            "data": None,
            "status": False,
            "message": str(e)
        }


@router.post("/{store_id}/address", status_code=201)
async def add_store_address(
        data: StoreAddressCreate,
        store_id: int = Path(..., description="Store ID"),
        db: AsyncSession = Depends(get_db),
):
    try:
        address_data = await StoreService.add_store_address(
            db=db,
            store_id=store_id,
            data=data
        )
        return {
            "data": StoreAddressResponse(**address_data),
            "status": True
        }
    except HTTPException as http_exc:
        raise http_exc
    except Exception as e:
        return {"data": None, "status": False, "message": str(e)}


@router.patch("/{store_id}/address/{store_address_id}", status_code=200)
async def patch_store_address(
        store_id: int = Path(..., description="Store ID"),
        store_address_id: int = Path(..., description="Store Address ID"),
        update_data: StoreAddressUpdate = Body(...),
        db: AsyncSession = Depends(get_db),
):
    try:
        updated_address = await StoreService.update_store_address(
            db=db,
            store_id=store_id,
            store_address_id=store_address_id,
            update_data=update_data
        )
        return {
            "data": StoreAddressResponse(**updated_address),
            "status": True
        }
    except HTTPException as http_exc:
        raise http_exc
    except Exception as e:
        return {"data": None, "status": False, "message": str(e)}


@router.get("/{store_id}/address")
async def get_store_addresses(
        store_id: int = Path(..., description="Store ID"),
        page: int = Query(1, ge=1),
        limit: int = Query(10, ge=1),
        needle: Optional[str] = Query(None),
        city_id: Optional[int] = Query(None),
        zone_id: Optional[int] = Query(None),
        db: AsyncSession = Depends(get_db)
):
    try:
        filters = StoreAddressFilter(search=needle, city_id=city_id, zone_id=zone_id)
        rows, total = await StoreService.get_store_addresses(
            db=db,
            store_id=store_id,
            filters=filters,
            page=page,
            limit=limit
        )

        data = []
        for address, city_name, zone_name in rows:
            item = StoreAddressResponse.model_validate(address).model_dump()
            item["city_name"] = city_name
            item["zone_name"] = zone_name
            data.append(item)

        return {
            "data": data,
            "total": total,
            "page": page,
            "limit": limit,
            "status": True
        }
    except Exception as e:
        return {"data": None, "status": False, "message": str(e)}


@router.delete("/{store_id}/address/{store_address_id}")
async def delete_store_address(
        store_id: int = Path(..., description="Store ID"),
        store_address_id: int = Path(..., description="Store Address ID"),
        db: AsyncSession = Depends(get_db),
):
    try:
        await StoreService.delete_store_address(
            db=db,
            store_id=store_id,
            store_address_id=store_address_id
        )
        return {"data": "store address deleted",
                "status": True}
    except HTTPException as http_exc:
        raise http_exc
    except Exception as e:
        return {"data": None, "status": False, "message": str(e)}


@router.post("/{store_id}/products")
async def add_product_to_store(
        store_id: int,
        data: ProductStoreCreate,
        db: AsyncSession = Depends(get_db),
):
    # перевіряємо чи існує магазин
    store = await db.get(Store, store_id)
    if not store:
        raise HTTPException(status_code=404, detail="Магазин не знайдено")

    # перевіряємо чи існує продукт
    product = await db.get(Product, data.product_id)
    if not product:
        raise HTTPException(status_code=404, detail="Продукт не знайдено")

    new_link = ProductStore(
        product_id=data.product_id,
        store_id=store_id,
        price=data.price,
        price_old=data.price_old,
    )
    db.add(new_link)
    await db.commit()
    await db.refresh(new_link)

    return {
        "data": ProductStoreOut.from_orm(new_link),
        "status": True
    }