from typing import Annotated
from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func

from app.core.database import get_db
from app.core.audit import log_audit
from app.models.user import User
from app.models.category import TreeCategory
from app.models.tree import Tree
from app.schemas.admin import GlobalCategoryCreate, GlobalCategoryUpdate, GlobalCategoryResponse
from app.api.deps import require_admin

router = APIRouter(prefix="/admin/categories", tags=["admin-categories"])


@router.get("/global", response_model=list[GlobalCategoryResponse])
async def list_global_categories(
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(require_admin)],
):
    """List all global categories (account_id IS NULL)."""
    result = await db.execute(
        select(TreeCategory).where(TreeCategory.account_id.is_(None)).order_by(TreeCategory.name)
    )
    categories = result.scalars().all()

    responses = []
    for cat in categories:
        tree_count = await db.scalar(
            select(func.count()).select_from(Tree).where(
                Tree.category_id == cat.id, Tree.deleted_at.is_(None)
            )
        ) or 0
        responses.append(GlobalCategoryResponse(
            id=cat.id, name=cat.name, slug=cat.slug,
            description=cat.description if hasattr(cat, 'description') else None,
            account_id=cat.account_id, tree_count=tree_count,
        ))

    return responses


@router.post("/global", response_model=GlobalCategoryResponse, status_code=status.HTTP_201_CREATED)
async def create_global_category(
    data: GlobalCategoryCreate,
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(require_admin)],
):
    """Create a global category."""
    # Check slug uniqueness for global categories
    existing = await db.execute(
        select(TreeCategory).where(TreeCategory.slug == data.slug, TreeCategory.account_id.is_(None))
    )
    if existing.scalar_one_or_none():
        raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="Global category with this slug already exists")

    category = TreeCategory(name=data.name, slug=data.slug, account_id=None)
    db.add(category)
    await log_audit(db, current_user.id, "global_category.create", "category", details={"name": data.name})
    await db.commit()
    await db.refresh(category)

    return GlobalCategoryResponse(id=category.id, name=category.name, slug=category.slug, account_id=None, tree_count=0)


@router.put("/global/{category_id}", response_model=GlobalCategoryResponse)
async def update_global_category(
    category_id: UUID,
    data: GlobalCategoryUpdate,
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(require_admin)],
):
    """Update a global category."""
    result = await db.execute(
        select(TreeCategory).where(TreeCategory.id == category_id, TreeCategory.account_id.is_(None))
    )
    category = result.scalar_one_or_none()
    if not category:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Global category not found")

    if data.name is not None:
        category.name = data.name
    if data.slug is not None:
        # Check slug uniqueness
        existing = await db.execute(
            select(TreeCategory).where(
                TreeCategory.slug == data.slug, TreeCategory.account_id.is_(None), TreeCategory.id != category_id
            )
        )
        if existing.scalar_one_or_none():
            raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="Slug already exists")
        category.slug = data.slug

    await log_audit(db, current_user.id, "global_category.update", "category", category.id)
    await db.commit()
    await db.refresh(category)

    tree_count = await db.scalar(
        select(func.count()).select_from(Tree).where(Tree.category_id == category.id, Tree.deleted_at.is_(None))
    ) or 0

    return GlobalCategoryResponse(
        id=category.id, name=category.name, slug=category.slug,
        account_id=None, tree_count=tree_count,
    )


@router.delete("/global/{category_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_global_category(
    category_id: UUID,
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(require_admin)],
):
    """Delete (archive) a global category."""
    result = await db.execute(
        select(TreeCategory).where(TreeCategory.id == category_id, TreeCategory.account_id.is_(None))
    )
    category = result.scalar_one_or_none()
    if not category:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Global category not found")

    await log_audit(db, current_user.id, "global_category.delete", "category", category.id,
                    {"name": category.name})
    await db.delete(category)
    await db.commit()
