"""Legacy `/rest/...` JSON wrappers mirroring Automation API `/api` paths."""

from __future__ import annotations

from typing import Any

from fastapi import APIRouter, Depends, Query, Request, Response

from app.db.pool import Database
from app.dependencies import get_database
from app.vsphere.domain import vm_ops
from app.vsphere.errors import invalid_argument
from app.vsphere.rest import router as core
from app.vsphere.rest import tagging_rest
from app.vsphere.security.authz import require_privilege, require_read
from app.vsphere.security.session import SessionInfo

router = APIRouter(tags=["vSphere Legacy REST"])


def _value(payload: Any) -> dict[str, Any]:
    return {"value": payload}


@router.get("/rest/vcenter/vm")
async def rest_list_vms(
    database: Database = Depends(get_database),
    session: SessionInfo = Depends(require_read),
    names: list[str] | None = Query(default=None),
    power_states: list[str] | None = Query(default=None),
    hosts: list[str] | None = Query(default=None),
    folders: list[str] | None = Query(default=None),
    limit: int | None = Query(default=None, ge=1, le=5000),
    cursor: int = Query(default=0, ge=0),
) -> dict[str, Any]:
    payload = await core.list_vms(
        database=database,
        _=session,
        names=names,
        power_states=power_states,
        hosts=hosts,
        folders=folders,
        datacenters=None,
        clusters=None,
        resource_pools=None,
        limit=limit,
        cursor=cursor,
    )
    return _value(payload)


@router.get("/rest/vcenter/vm/{vm}")
async def rest_get_vm(
    vm: str,
    database: Database = Depends(get_database),
    session: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
    return _value(await core.get_vm(vm=vm, database=database, _=session))


@router.get("/rest/vcenter/host")
async def rest_list_hosts(
    database: Database = Depends(get_database),
    session: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
    return _value(await core.list_hosts(database=database, _=session))


@router.get("/rest/vcenter/datastore")
async def rest_list_datastores(
    database: Database = Depends(get_database),
    session: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
    return _value(await core.list_datastores(database=database, _=session))


@router.get("/rest/vcenter/network")
async def rest_list_networks(
    database: Database = Depends(get_database),
    session: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
    return _value(await core.list_networks(database=database, _=session))


@router.get("/rest/vcenter/datacenter")
async def rest_list_datacenters(
    database: Database = Depends(get_database),
    session: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
    return _value(await core.list_datacenters(database=database, _=session))


@router.get("/rest/vcenter/cluster")
async def rest_list_clusters(
    database: Database = Depends(get_database),
    session: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
    return _value(await core.list_clusters(database=database, _=session))


@router.get("/rest/appliance/system/version")
async def rest_appliance_version(
    request: Request,
    database: Database = Depends(get_database),
    _: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
    return _value(await core.appliance_version(request=request, database=database))


@router.post("/rest/vcenter/vm/{vm}/power")
async def rest_power_vm(
    vm: str,
    action: str = Query(...),
    database: Database = Depends(get_database),
    _: SessionInfo = Depends(require_privilege("VirtualMachine.Interact.PowerOn")),
) -> dict[str, Any]:
    task_id = await vm_ops.set_power(database, vm, action.lower())
    return _value({"task": task_id})


# --- CIS tagging (govmomi / terraform-provider-vsphere / pulumi-vsphere) ---


@router.get("/rest/com/vmware/cis/tagging/category")
async def rest_list_categories(
    database: Database = Depends(get_database),
    session: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
    return _value(await tagging_rest.list_categories(database=database, _=session))


@router.post("/rest/com/vmware/cis/tagging/category")
async def rest_category_action(
    body: dict[str, Any] | None = None,
    action: str | None = Query(default=None, alias="~action"),
    database: Database = Depends(get_database),
    session: SessionInfo = Depends(require_privilege("InventoryService.Tagging.CreateCategory")),
) -> Any:
    payload = body or {}
    act = (action or "create").lower()
    if act == "create":
        return _value(
            await tagging_rest.create_category(body=payload, database=database, _=session)
        )
    raise invalid_argument(f"unsupported ~action {act}")


@router.get("/rest/com/vmware/cis/tagging/category/{category_id}")
async def rest_get_category(
    category_id: str,
    database: Database = Depends(get_database),
    session: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
    return _value(
        await tagging_rest.get_category(category_id=category_id, database=database, _=session)
    )


@router.delete("/rest/com/vmware/cis/tagging/category/{category_id}")
async def rest_delete_category(
    category_id: str,
    database: Database = Depends(get_database),
    session: SessionInfo = Depends(require_privilege("InventoryService.Tagging.CreateCategory")),
) -> Response:
    return await tagging_rest.delete_category(category_id=category_id, database=database, _=session)


@router.get("/rest/com/vmware/cis/tagging/tag")
async def rest_list_tags(
    database: Database = Depends(get_database),
    session: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
    return _value(await tagging_rest.list_tags(database=database, _=session))


@router.post("/rest/com/vmware/cis/tagging/tag")
async def rest_tag_action(
    body: dict[str, Any] | None = None,
    action: str | None = Query(default=None, alias="~action"),
    database: Database = Depends(get_database),
    session: SessionInfo = Depends(require_privilege("InventoryService.Tagging.CreateTag")),
) -> Any:
    payload = body or {}
    act = (action or "create").lower()
    if act == "create":
        return _value(await tagging_rest.create_tag(body=payload, database=database, _=session))
    raise invalid_argument(f"unsupported ~action {act}")


@router.get("/rest/com/vmware/cis/tagging/tag/{tag_id}")
async def rest_get_tag(
    tag_id: str,
    database: Database = Depends(get_database),
    session: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
    return _value(await tagging_rest.get_tag(tag_id=tag_id, database=database, _=session))


@router.delete("/rest/com/vmware/cis/tagging/tag/{tag_id}")
async def rest_delete_tag(
    tag_id: str,
    database: Database = Depends(get_database),
    session: SessionInfo = Depends(require_privilege("InventoryService.Tagging.CreateTag")),
) -> Response:
    return await tagging_rest.delete_tag(tag_id=tag_id, database=database, _=session)


@router.post("/rest/com/vmware/cis/tagging/tag-association")
async def rest_tag_association(
    request: Request,
    body: dict[str, Any] | None = None,
    action: str | None = Query(default=None, alias="~action"),
    database: Database = Depends(get_database),
    session: SessionInfo = Depends(require_privilege("InventoryService.Tagging.AttachTag")),
) -> Any:
    """govmomi/terraform use ``?~action=`` instead of JSON ``action``."""

    payload = dict(body or {})
    # Some clients send ``?~action=``; FastAPI alias can miss ``~`` — also read raw query.
    resolved = (
        action
        or request.query_params.get("~action")
        or request.query_params.get("action")
        or payload.get("action")
    )
    if resolved:
        payload["action"] = resolved
    result = await tagging_rest.tag_association(
        body=payload,
        action=str(resolved) if resolved else None,
        database=database,
        _=session,
    )
    if isinstance(result, Response):
        return result
    return _value(result)
