import uuid

from fastapi import APIRouter, Query

from app.api.deps import AdminDep, ClientDep, PageDep, SessionDep
from app.api.serializers import dump, dump_list
from app.core.response import paginated, success
from app.flows import FLOWS
from app.schemas import (
    CategoryCreate,
    CategoryOut,
    CategoryUpdate,
    ProductCreate,
    ProductOut,
    ProductUpdate,
)
from app.services import ProductService

router = APIRouter(tags=["catalog"])


# -- categories -----------------------------------------------------
@router.get("/categories")
async def list_categories(
    session: SessionDep, _: ClientDep, enabled: bool = Query(default=True)
) -> dict:
    categories = await ProductService(session).list_categories(only_enabled=enabled)
    return success(dump_list(CategoryOut, categories))


@router.post("/categories")
async def create_category(payload: CategoryCreate, session: SessionDep, _: AdminDep) -> dict:
    category = await ProductService(session).create_category(**payload.model_dump())
    return success(dump(CategoryOut, category), "created")


@router.put("/categories/{category_id}")
async def update_category(
    category_id: uuid.UUID, payload: CategoryUpdate, session: SessionDep, _: AdminDep
) -> dict:
    category = await ProductService(session).update_category(
        category_id, **payload.model_dump(exclude_unset=True)
    )
    return success(dump(CategoryOut, category), "updated")


@router.delete("/categories/{category_id}")
async def delete_category(category_id: uuid.UUID, session: SessionDep, _: AdminDep) -> dict:
    await ProductService(session).delete_category(category_id)
    return success(None, "deleted")


@router.get("/categories/{slug}/products")
async def category_products(slug: str, session: SessionDep, _: ClientDep) -> dict:
    products = await ProductService(session).list_by_category_slug(slug)
    return success(dump_list(ProductOut, products))


# -- products -------------------------------------------------------
@router.get("/products")
async def list_products(
    session: SessionDep,
    _: ClientDep,
    page_params: PageDep,
    category_id: uuid.UUID | None = None,
    flow: str | None = None,
    enabled: bool | None = None,
    paginate: bool = Query(default=False),
) -> dict:
    service = ProductService(session)
    filters = {
        "category_id": category_id,
        "flow": flow,
        "enabled": enabled,
        "search": page_params.search,
    }
    if paginate:
        items, total = await service.search_products(page_params.page, page_params.size, **filters)
        return success(
            paginated(dump_list(ProductOut, items), total, page_params.page, page_params.size)
        )
    products = await service.list_products(**filters)
    return success(dump_list(ProductOut, products))


@router.get("/products/{product_id}")
async def get_product(product_id: uuid.UUID, session: SessionDep, _: ClientDep) -> dict:
    product = await ProductService(session).get_product(product_id)
    return success(dump(ProductOut, product))


@router.post("/products")
async def create_product(payload: ProductCreate, session: SessionDep, _: AdminDep) -> dict:
    product = await ProductService(session).create_product(**payload.model_dump())
    return success(dump(ProductOut, product), "created")


@router.put("/products/{product_id}")
async def update_product(
    product_id: uuid.UUID, payload: ProductUpdate, session: SessionDep, _: AdminDep
) -> dict:
    product = await ProductService(session).update_product(
        product_id, **payload.model_dump(exclude_unset=True)
    )
    return success(dump(ProductOut, product), "updated")


@router.post("/products/{product_id}/duplicate")
async def duplicate_product(product_id: uuid.UUID, session: SessionDep, _: AdminDep) -> dict:
    product = await ProductService(session).duplicate_product(product_id)
    return success(dump(ProductOut, product), "duplicated")


@router.delete("/products/{product_id}")
async def delete_product(product_id: uuid.UUID, session: SessionDep, _: AdminDep) -> dict:
    await ProductService(session).delete_product(product_id)
    return success(None, "deleted")


# -- flows ----------------------------------------------------------
@router.get("/flows")
async def list_flows(_: ClientDep) -> dict:
    return success(
        [
            {
                "name": flow.name,
                "productless": flow.productless,
                "steps": [step.to_dict() for step in flow.get_steps(None)],
                "options": [option.to_dict() for option in flow.get_options(None)],
            }
            for flow in FLOWS.values()
        ]
    )


@router.get("/flows/{name}")
async def get_flow_definition(
    name: str, session: SessionDep, _: ClientDep, product_id: uuid.UUID | None = None
) -> dict:
    from app.flows import get_flow

    flow = get_flow(name)
    product = await ProductService(session).get_product(product_id) if product_id else None
    return success(
        {
            "name": flow.name,
            "productless": flow.productless,
            "steps": [step.to_dict() for step in flow.get_steps(product)],
            "options": [option.to_dict() for option in flow.get_options(product)],
        }
    )
