"""Users and cohorts router."""
from uuid import UUID

from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload

from app.api.deps import get_current_user, require_roles
from app.core.rbac import Role
from app.db.base import get_db
from app.models import CohortMember, CohortModel, ProgramModel, UserModel
from app.schemas import CohortCreate, CohortOut, UserOut

router = APIRouter(prefix="/api/v1", tags=["users-cohorts"])


@router.get("/users", response_model=list[UserOut])
async def list_users(
    db: AsyncSession = Depends(get_db),
    current_user: UserModel = Depends(require_roles(Role.LD_ADMIN, Role.SALES_MANAGER, Role.DEPT_HEAD)),
) -> list[UserOut]:
    result = await db.execute(
        select(UserModel)
        .where(UserModel.is_active == True)
        .options(selectinload(UserModel.roles))
        .order_by(UserModel.full_name)
    )
    users = result.scalars().all()
    out = []
    for u in users:
        u._role_names = [r.name for r in u.roles]
        out.append(UserOut(
            id=u.id, email=u.email, full_name=u.full_name,
            display_name=u.display_name, is_active=u.is_active,
            roles=[r.name for r in u.roles],
        ))
    return out


@router.get("/me", response_model=UserOut)
async def get_me(
    current_user: UserModel = Depends(get_current_user),
) -> UserOut:
    return UserOut(
        id=current_user.id, email=current_user.email,
        full_name=current_user.full_name, display_name=current_user.display_name,
        is_active=current_user.is_active,
        roles=getattr(current_user, "_role_names", []),
    )


@router.post("/cohorts", response_model=CohortOut, status_code=201)
async def create_cohort(
    body: CohortCreate,
    db: AsyncSession = Depends(get_db),
    current_user: UserModel = Depends(require_roles(Role.LD_ADMIN, Role.DEPT_HEAD)),
) -> CohortOut:
    # Verify program exists
    program = await db.get(ProgramModel, body.program_id)
    if not program:
        raise HTTPException(status_code=404, detail="Program not found")

    cohort = CohortModel(
        name=body.name,
        program_id=body.program_id,
        batch_size=body.batch_size,
        is_active=body.is_active,
    )
    db.add(cohort)
    await db.commit()
    await db.refresh(cohort)
    return CohortOut.model_validate(cohort)


@router.put("/cohorts/{cohort_id}", response_model=CohortOut)
async def update_cohort(
    cohort_id: UUID,
    body: CohortCreate,
    db: AsyncSession = Depends(get_db),
    current_user: UserModel = Depends(require_roles(Role.LD_ADMIN, Role.DEPT_HEAD)),
) -> CohortOut:
    cohort = await db.get(CohortModel, cohort_id)
    if not cohort:
        raise HTTPException(status_code=404, detail="Cohort not found")

    cohort.name = body.name
    cohort.program_id = body.program_id
    cohort.batch_size = body.batch_size
    cohort.is_active = body.is_active
    await db.commit()
    await db.refresh(cohort)
    return CohortOut.model_validate(cohort)


@router.post("/cohorts/{cohort_id}/members", status_code=201)
async def add_cohort_member(
    cohort_id: UUID,
    user_id: UUID,
    db: AsyncSession = Depends(get_db),
    current_user: UserModel = Depends(require_roles(Role.LD_ADMIN, Role.DEPT_HEAD)),
) -> dict:
    # Check not already member
    result = await db.execute(
        select(CohortMember).where(
            CohortMember.cohort_id == cohort_id,
            CohortMember.user_id == user_id,
        )
    )
    if result.scalar_one_or_none():
        raise HTTPException(status_code=409, detail="User already in cohort")

    member = CohortMember(cohort_id=cohort_id, user_id=user_id)
    db.add(member)
    await db.commit()
    return {"message": "Member added"}
