import uuid
from typing import Any
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from pydantic import BaseModel
from app.database import get_db
from app.models.template import Template
from app.utils.auth import get_current_user, require_admin
from app.models.user import User

router = APIRouter(prefix="/templates", tags=["templates"])


class TemplateOut(BaseModel):
    id: uuid.UUID
    name: str
    category_key: str
    standard_fields: Any
    component_schema: Any
    description: str | None
    is_active: bool

    model_config = {"from_attributes": True}


class TemplateUpdate(BaseModel):
    name: str | None = None
    description: str | None = None
    is_active: bool | None = None
    standard_fields: Any = None
    component_schema: Any = None


@router.get("", response_model=list[TemplateOut])
async def list_templates(
    include_inactive: bool = False,
    user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    q = select(Template)
    # Non-admins always see only active templates
    if not include_inactive or user.role.value != "admin":
        q = q.where(Template.is_active == True)
    result = await db.execute(q)
    return result.scalars().all()


@router.get("/{template_id}", response_model=TemplateOut)
async def get_template(
    template_id: uuid.UUID,
    user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    result = await db.execute(select(Template).where(Template.id == template_id))
    t = result.scalar_one_or_none()
    if not t:
        raise HTTPException(404, detail="Template not found")
    return t


@router.patch("/{template_id}", response_model=TemplateOut)
async def update_template(
    template_id: uuid.UUID,
    body: TemplateUpdate,
    user: User = Depends(require_admin),
    db: AsyncSession = Depends(get_db),
):
    result = await db.execute(select(Template).where(Template.id == template_id))
    t = result.scalar_one_or_none()
    if not t:
        raise HTTPException(404, detail="Template not found")

    for field, val in body.model_dump(exclude_unset=True).items():
        setattr(t, field, val)
    await db.commit()
    await db.refresh(t)
    return t
