"""Workspaces router: list, create, switch."""

from __future__ import annotations

import re
import uuid

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session

from legate.api.deps import get_current_user
from legate.api.schemas import (
    SwitchResponse,
    WorkspaceCreate,
    WorkspaceCreateResponse,
    WorkspaceOut,
)
from legate.audit.service import record as audit_record
from legate.db.models.user import User
from legate.db.session import get_db
from legate.policy.roles import Role
from legate.repositories import workspaces as workspaces_repo
from legate.security.tokens import create_access_token

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


def _slugify(value: str) -> str:
    slug = re.sub(r"[^a-z0-9]+", "-", value.lower()).strip("-")
    return slug or "workspace"


def _unique_slug(db: Session, base: str) -> str:
    slug = base
    suffix = 1
    while workspaces_repo.get_by_slug(db, slug) is not None:
        suffix += 1
        slug = f"{base}-{suffix}"
    return slug


@router.get("", response_model=list[WorkspaceOut])
def list_workspaces(
    user: User = Depends(get_current_user), db: Session = Depends(get_db)
) -> list[WorkspaceOut]:
    workspaces = workspaces_repo.list_for_user(db, user.id)
    out: list[WorkspaceOut] = []
    for ws in workspaces:
        membership = workspaces_repo.get_membership(db, user_id=user.id, workspace_id=ws.id)
        item = WorkspaceOut.model_validate(ws)
        item.role = membership.role if membership else None
        out.append(item)
    return out


@router.post("", response_model=WorkspaceCreateResponse, status_code=status.HTTP_201_CREATED)
def create_workspace(
    body: WorkspaceCreate,
    user: User = Depends(get_current_user),
    db: Session = Depends(get_db),
) -> WorkspaceCreateResponse:
    base_slug = _slugify(body.slug or body.name)
    slug = _unique_slug(db, base_slug)

    workspace = workspaces_repo.create(db, name=body.name, slug=slug)
    # The creator becomes the workspace Owner.
    workspaces_repo.add_member(db, user_id=user.id, workspace_id=workspace.id, role=Role.OWNER)
    audit_record(
        db,
        workspace_id=workspace.id,
        actor=f"user:{user.id}",
        action="workspace.create",
        target=str(workspace.id),
        metadata={"name": workspace.name, "slug": workspace.slug},
    )
    db.commit()
    db.refresh(workspace)

    out = WorkspaceOut.model_validate(workspace)
    out.role = Role.OWNER
    return WorkspaceCreateResponse(
        workspace=out,
        # A fresh access token scoped to the new workspace, so the caller can act in it immediately.
        access_token=create_access_token(user.id, workspace.id),
    )


@router.post("/{workspace_id}/switch", response_model=SwitchResponse)
def switch_workspace(
    workspace_id: uuid.UUID,
    user: User = Depends(get_current_user),
    db: Session = Depends(get_db),
) -> SwitchResponse:
    membership = workspaces_repo.get_membership(db, user_id=user.id, workspace_id=workspace_id)
    if membership is None:
        raise HTTPException(status.HTTP_403_FORBIDDEN, detail="not a member of this workspace")
    return SwitchResponse(
        access_token=create_access_token(user.id, workspace_id),
        workspace_id=workspace_id,
    )
