# retoor <retoor@molodetz.nl>

import asyncio
from typing import Annotated

from fastapi import APIRouter, Depends, Request
from fastapi.responses import JSONResponse

from devplacepy.database import get_projects_by_uids, get_table, get_users_by_uids
from devplacepy.dependencies import json_or_form
from devplacepy.models import (
    EditorPrefsForm,
    WorkspaceFlagForm,
    WorkspaceQuotaForm,
    WorkspaceSuspendForm,
)
from devplacepy.responses import action_result, json_error, respond
from devplacepy.routers.admin._shared import deny_senior, is_senior_admin
from devplacepy.schemas import AdminWorkspacesOut
from devplacepy.seo import base_seo_context
from devplacepy.services.audit import record as audit
from devplacepy.services.containers import store
from devplacepy.services.containers.workspace import (
    editor,
    flags,
    provision,
    quota,
    tunnels,
)
from devplacepy.utils import create_notification, generate_uid, not_found, require_admin

router = APIRouter()


async def _decorate(rows: list[dict]) -> list[dict]:
    owner_uids = {row.get("workspace_owner_uid") for row in rows if row.get("workspace_owner_uid")}
    owners = get_users_by_uids(list(owner_uids)) if owner_uids else {}
    project_uids = {row.get("project_uid") for row in rows if row.get("project_uid")}
    projects = get_projects_by_uids(list(project_uids)) if project_uids else {}
    views = await asyncio.gather(*(provision.view(row) for row in rows))
    decorated = []
    for row, view in zip(rows, views):
        owner = owners.get(row.get("workspace_owner_uid", "")) or {}
        project = projects.get(row.get("project_uid", "")) or {}
        view["owner_username"] = owner.get("username", "")
        view["project_title"] = project.get("title", "")
        view["project_slug"] = project.get("slug", "") or project.get("uid", "")
        decorated.append(view)
    return decorated


def _all_workspaces() -> list[dict]:
    return list(get_table("instances").find(is_workspace=1, deleted_at=None))


def _instance_or_404(uid: str) -> dict:
    instance = store.get_instance(uid)
    if not instance or not instance.get("is_workspace"):
        raise not_found("Workspace not found")
    return instance


def _audit(request: Request, admin: dict, event_key: str, instance: dict, **extra):
    audit.record(
        request,
        event_key,
        user=admin,
        target_type="instance",
        target_uid=instance["uid"],
        target_label=instance.get("name"),
        summary=f"{admin['username']} {event_key} workspace {instance.get('name')}",
        links=[audit.instance(instance["uid"], instance.get("name"))],
        **extra,
    )


@router.get("/workspaces")
async def admin_workspaces(request: Request):
    admin = require_admin(request)
    if not isinstance(admin, dict):
        return admin
    context = {
        "workspaces": await _decorate(_all_workspaces()),
        "flags": flags.list_flags(),
        "admin_section": "workspaces",
        "user": admin,
        **base_seo_context(
            request,
            title="Workspaces - Admin",
            description="Administer dev workspaces.",
            robots="noindex,nofollow",
            breadcrumbs=[
                {"name": "Home", "url": "/feed"},
                {"name": "Admin", "url": "/admin"},
                {"name": "Workspaces", "url": "/admin/workspaces"},
            ],
        ),
    }
    return respond(request, "admin_workspaces.html", context, model=AdminWorkspacesOut)


@router.get("/workspaces/data")
async def admin_workspaces_data(request: Request):
    admin = require_admin(request)
    if not isinstance(admin, dict):
        return admin
    return JSONResponse(
        {"workspaces": await _decorate(_all_workspaces()), "flags": flags.list_flags()}
    )


@router.post("/workspaces/{uid}/suspend")
async def admin_workspace_suspend(
    request: Request,
    uid: str,
    data: Annotated[WorkspaceSuspendForm, Depends(json_or_form(WorkspaceSuspendForm))],
):
    admin = require_admin(request)
    if not isinstance(admin, dict):
        return admin
    instance = _instance_or_404(uid)
    reason = (data.reason or "").strip()
    if not reason:
        return json_error(400, "a reason is required and is shown to the owner")
    provision.suspend(instance, admin["uid"], reason)
    _audit(request, admin, "container.workspace.suspend", instance, metadata={"reason": reason})
    owner = instance.get("workspace_owner_uid", "")
    if owner:
        create_notification(
            owner,
            "workspace",
            f"Workspace {instance.get('name', '')} was suspended: {reason}",
            instance["uid"],
            "/projects",
        )
    return action_result(request, "/admin/workspaces")


@router.post("/workspaces/{uid}/unsuspend")
async def admin_workspace_unsuspend(request: Request, uid: str):
    admin = require_admin(request)
    if not isinstance(admin, dict):
        return admin
    instance = _instance_or_404(uid)
    provision.unsuspend(instance)
    _audit(request, admin, "container.workspace.unsuspend", instance)
    owner = instance.get("workspace_owner_uid", "")
    if owner:
        create_notification(
            owner,
            "workspace",
            f"Workspace {instance.get('name', '')} is available again.",
            instance["uid"],
            "/projects",
        )
    return action_result(request, "/admin/workspaces")


@router.post("/workspaces/{uid}/stop")
async def admin_workspace_stop(request: Request, uid: str):
    admin = require_admin(request)
    if not isinstance(admin, dict):
        return admin
    instance = _instance_or_404(uid)
    provision.stop(instance)
    _audit(request, admin, "container.workspace.stop", instance)
    return action_result(request, "/admin/workspaces")


@router.post("/workspaces/{uid}/start")
async def admin_workspace_start(request: Request, uid: str):
    admin = require_admin(request)
    if not isinstance(admin, dict):
        return admin
    instance = _instance_or_404(uid)
    store.update_instance(instance["uid"], {"desired_state": "running"})
    _audit(request, admin, "container.workspace.resume", instance)
    return action_result(request, "/admin/workspaces")


@router.post("/workspaces/{uid}/delete")
async def admin_workspace_delete(request: Request, uid: str):
    admin = require_admin(request)
    if not isinstance(admin, dict):
        return admin
    instance = _instance_or_404(uid)
    for row in tunnels.list_for_instance(instance["uid"]):
        tunnels.soft_delete(row["uid"], admin["uid"])
    store.delete_instance(instance["uid"], admin["uid"])
    _audit(request, admin, "container.workspace.delete", instance)
    return action_result(request, "/admin/workspaces")


@router.post("/workspaces/{uid}/flag")
async def admin_workspace_flag(
    request: Request,
    uid: str,
    data: Annotated[WorkspaceFlagForm, Depends(json_or_form(WorkspaceFlagForm))],
):
    admin = require_admin(request)
    if not isinstance(admin, dict):
        return admin
    instance = _instance_or_404(uid)
    row = flags.raise_flag(
        instance, data.kind or flags.KIND_MANUAL, data.severity, data.detail
    )
    _audit(request, admin, "container.workspace.flag.raise", instance,
           metadata={"kind": data.kind, "severity": data.severity})
    owner = instance.get("workspace_owner_uid", "")
    if owner:
        create_notification(
            owner,
            "workspace",
            f"Workspace {instance.get('name', '')} was flagged: {data.detail or data.kind}",
            instance["uid"],
            "/projects",
        )
    return action_result(request, "/admin/workspaces", data=row)


@router.post("/workspaces/flags/{flag_uid}/resolve")
async def admin_flag_resolve(request: Request, flag_uid: str, status: str = "resolved"):
    admin = require_admin(request)
    if not isinstance(admin, dict):
        return admin
    if not flags.set_status(flag_uid, status, admin["uid"]):
        raise not_found("Flag not found")
    event = (
        "container.workspace.flag.dismiss"
        if status == "dismissed"
        else "container.workspace.flag.resolve"
    )
    audit.record(
        request,
        event,
        user=admin,
        target_type="workspace_flag",
        target_uid=flag_uid,
        summary=f"{admin['username']} set flag {flag_uid} to {status}",
    )
    return action_result(request, "/admin/workspaces")


@router.post("/workspaces/{uid}/editor")
async def admin_workspace_editor(
    request: Request,
    uid: str,
    data: Annotated[EditorPrefsForm, Depends(json_or_form(EditorPrefsForm))],
):
    admin = require_admin(request)
    if not isinstance(admin, dict):
        return admin
    instance = _instance_or_404(uid)
    owner_uid = instance.get("workspace_owner_uid", "")
    owner = get_users_by_uids([owner_uid]).get(owner_uid) if owner_uid else None
    if is_senior_admin(admin, owner):
        return deny_senior(
            request,
            admin,
            owner_uid,
            owner,
            "container.workspace.editor.update",
            "/admin/workspaces",
        )
    if not owner_uid:
        return json_error(400, "this workspace has no owner")
    if data.reset:
        editor.reset_prefs(owner_uid, admin["uid"])
    else:
        editor.save_prefs(
            owner_uid, data.model_dump(exclude={"reset"}, exclude_unset=True)
        )
    _audit(request, admin, "container.workspace.editor.update", instance)
    return action_result(
        request,
        "/admin/workspaces",
        data={"editor": editor.view(owner_uid, instance)},
    )


@router.post("/workspaces/quota")
async def admin_workspace_quota(
    request: Request,
    data: Annotated[WorkspaceQuotaForm, Depends(json_or_form(WorkspaceQuotaForm))],
):
    admin = require_admin(request)
    if not isinstance(admin, dict):
        return admin
    if not data.owner_id:
        return json_error(400, "owner_id is required")
    table = get_table(quota.RULES_TABLE)
    existing = table.find_one(
        owner_kind="user", owner_id=data.owner_id, deleted_at=None
    )
    payload = {key: getattr(data, key) for key in quota.RULE_COLUMNS}
    if existing:
        table.update({"uid": existing["uid"], "label": data.label, **payload}, ["uid"])
        uid = existing["uid"]
    else:
        uid = generate_uid()
        table.insert(
            {
                "uid": uid,
                "owner_kind": "user",
                "owner_id": data.owner_id,
                "label": data.label,
                "created_at": "",
                "updated_at": "",
                "deleted_at": None,
                "deleted_by": None,
                **payload,
            }
        )
    audit.record(
        request,
        "container.workspace.settings.update",
        user=admin,
        target_type="user",
        target_uid=data.owner_id,
        summary=f"{admin['username']} updated workspace quota",
        metadata=payload,
    )
    return action_result(request, "/admin/workspaces", data={"uid": uid, **payload})
