"""
Who's signed in to the workspace, for its administrators — and signing a
session, a person, or everyone out (app/crud/sessions.py). Your own
sessions are under /auth/sessions.
"""

import uuid

from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.database import get_db
from app.core.permissions import deny_vendor, require_permission
from app.core.security import AuthContext, get_auth_context
from app.crud import sessions
from app.crud.audit import write_audit_log
from app.models.identity import User

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


@router.get("", response_model=list[sessions.SessionRead])
async def list_sessions(
    ctx: AuthContext = Depends(get_auth_context),
    db: AsyncSession = Depends(get_db),
    _: AuthContext = Depends(require_permission("users_roles", "view")),
    __: AuthContext = Depends(deny_vendor()),
) -> list[sessions.SessionRead]:
    """Every live session in the workspace, most recently active first."""
    return await sessions.live(db, ctx.tenant_id, current=ctx.session_id)


@router.post("/{session_id}/revoke", status_code=204)
async def revoke_session(
    session_id: uuid.UUID,
    ctx: AuthContext = Depends(get_auth_context),
    db: AsyncSession = Depends(get_db),
    _: AuthContext = Depends(require_permission("users_roles", "edit")),
    __: AuthContext = Depends(deny_vendor()),
) -> None:
    if not await sessions.revoke(db, ctx.tenant_id, session_id):
        raise HTTPException(status_code=404, detail="Session not found.")
    await write_audit_log(db, ctx.tenant_id, ctx.user_id, "session.revoked", "session", session_id)


@router.post("/users/{user_id}/revoke", status_code=204)
async def sign_out_user(
    user_id: uuid.UUID,
    ctx: AuthContext = Depends(get_auth_context),
    db: AsyncSession = Depends(get_db),
    _: AuthContext = Depends(require_permission("users_roles", "edit")),
    __: AuthContext = Depends(deny_vendor()),
) -> None:
    """Signs a person out everywhere."""
    user = await db.get(User, user_id)
    if user is None or user.tenant_id != ctx.tenant_id:
        raise HTTPException(status_code=404, detail="User not found.")
    await sessions.sign_out_everywhere(db, user)
    await write_audit_log(db, ctx.tenant_id, ctx.user_id, "user.signed_out_everywhere", "user", user_id)


class SignedOut(BaseModel):
    people: int


@router.post("/revoke-everyone", response_model=SignedOut)
async def sign_out_everyone(
    ctx: AuthContext = Depends(get_auth_context),
    db: AsyncSession = Depends(get_db),
    _: AuthContext = Depends(require_permission("settings", "edit")),
    __: AuthContext = Depends(deny_vendor()),
) -> SignedOut:
    """Signs everyone in the workspace out, except whoever asks."""
    people = await sessions.sign_out_everyone(db, ctx.tenant_id, keep_user=ctx.user_id)
    await write_audit_log(db, ctx.tenant_id, ctx.user_id, "tenant.signed_out_everyone", "tenant", ctx.tenant_id, {"people": people})
    return SignedOut(people=people)
