"""Departments CRUD."""
from datetime import datetime, timezone
from bson import ObjectId
from bson.errors import InvalidId
from fastapi import APIRouter, Depends, HTTPException

from deps import get_db, get_current_user, require_roles
from models import DepartmentIn

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


def _oid(s):
    try: return ObjectId(s)
    except InvalidId: raise HTTPException(status_code=400, detail="ID inválido")


def _ser(d: dict) -> dict:
    return {
        "id": str(d["_id"]),
        "name": d["name"],
        "description": d.get("description", ""),
        "color": d.get("color", "#00E599"),
        "created_at": d.get("created_at"),
        "member_count": d.get("member_count", 0),
    }


@router.get("")
async def list_departments(_: dict = Depends(get_current_user)):
    db = get_db()
    cursor = db.departments.find({}).sort("name", 1)
    items = []
    async for d in cursor:
        d["member_count"] = await db.users.count_documents({"department_id": str(d["_id"])})
        items.append(_ser(d))
    return items


@router.post("")
async def create_department(payload: DepartmentIn, _: dict = Depends(require_roles("ceo", "admin"))):
    db = get_db()
    if await db.departments.find_one({"name": payload.name}):
        raise HTTPException(status_code=400, detail="Ya existe un departamento con ese nombre")
    now = datetime.now(timezone.utc).isoformat()
    doc = {**payload.model_dump(), "created_at": now}
    r = await db.departments.insert_one(doc)
    doc["_id"] = r.inserted_id
    # auto-create department channel
    await db.channels.insert_one({
        "name": f"Depto: {payload.name}",
        "type": "department",
        "department_id": str(r.inserted_id),
        "project_id": None,
        "members": [],
        "created_at": now,
    })
    return _ser(doc)


@router.patch("/{dept_id}")
async def update_department(dept_id: str, payload: DepartmentIn, _: dict = Depends(require_roles("ceo", "admin"))):
    db = get_db()
    oid = _oid(dept_id)
    r = await db.departments.find_one_and_update({"_id": oid}, {"$set": payload.model_dump()}, return_document=True)
    if not r:
        raise HTTPException(status_code=404, detail="Departamento no encontrado")
    return _ser(r)


@router.delete("/{dept_id}")
async def delete_department(dept_id: str, _: dict = Depends(require_roles("ceo", "admin"))):
    db = get_db()
    oid = _oid(dept_id)
    # remove department_id from users
    await db.users.update_many({"department_id": dept_id}, {"$unset": {"department_id": ""}})
    await db.channels.delete_many({"department_id": dept_id})
    r = await db.departments.delete_one({"_id": oid})
    if r.deleted_count == 0:
        raise HTTPException(status_code=404, detail="Departamento no encontrado")
    return {"ok": True}


@router.get("/{dept_id}/members")
async def department_members(dept_id: str, _: dict = Depends(get_current_user)):
    db = get_db()
    cur = db.users.find({"department_id": dept_id}).sort("name", 1)
    return [
        {"id": str(u["_id"]), "name": u["name"], "email": u["email"], "role": u["role"], "active": u.get("active", True)}
        async for u in cur
    ]
