"""Content library, OVF deploy, storage policies, privileges."""

from __future__ import annotations

from typing import Any

from fastapi import APIRouter, Depends, Query, Response

from app.db.pool import Database
from app.dependencies import get_database
from app.vsphere.domain import api_state, content
from app.vsphere.security.authz import require_privilege, require_read
from app.vsphere.security.session import SessionInfo

router = APIRouter(tags=["vSphere Content"])


@router.get("/api/content/library")
async def list_libraries(
    database: Database = Depends(get_database), _: SessionInfo = Depends(require_read)
) -> list[str]:
    return [item["id"] for item in await content.list_libraries(database)]


@router.get("/api/content/local-library")
async def list_local_libraries(
    database: Database = Depends(get_database), _: SessionInfo = Depends(require_read)
) -> list[str]:
    return [
        item["id"]
        for item in await content.list_libraries(database)
        if str(item.get("type") or "LOCAL").upper() == "LOCAL"
    ]


@router.post("/api/content/local-library")
async def create_library(
    body: dict[str, Any],
    database: Database = Depends(get_database),
    _: SessionInfo = Depends(require_privilege("ContentLibrary.CreateLocalLibrary")),
) -> str:
    from app.vsphere.errors import invalid_argument

    spec = body.get("create_spec") or body
    name = spec.get("name") if isinstance(spec, dict) else None
    if not name:
        raise invalid_argument("create_spec.name is required")
    return await content.create_library(
        database, name=str(name), description=str(spec.get("description") or "")
    )


# Static /library/item* paths must win over /library/{library_id}.
@router.get("/api/content/library/item")
async def list_items(
    library_id: str = Query(...),
    database: Database = Depends(get_database),
    _: SessionInfo = Depends(require_read),
) -> list[str]:
    return [item["id"] for item in await content.list_library_items(database, library_id)]


@router.post("/api/content/library/item")
async def create_item(
    body: dict[str, Any],
    database: Database = Depends(get_database),
    _: SessionInfo = Depends(require_privilege("ContentLibrary.AddLibraryItem")),
) -> str:
    from app.vsphere.errors import invalid_argument

    spec = body.get("create_spec") or body
    if not isinstance(spec, dict):
        raise invalid_argument("create_spec is required")
    library_id = spec.get("library_id")
    name = spec.get("name")
    if not library_id:
        raise invalid_argument("create_spec.library_id is required")
    if not name:
        raise invalid_argument("create_spec.name is required")
    return await content.create_library_item(
        database,
        library_id=str(library_id),
        name=str(name),
        item_type=str(spec.get("type") or "ovf"),
        description=str(spec.get("description") or ""),
    )


@router.post("/api/content/library/item/update-session")
async def create_update_session(
    body: dict[str, Any],
    database: Database = Depends(get_database),
    _: SessionInfo = Depends(require_privilege("ContentLibrary.AddLibraryItem")),
) -> str:
    create_spec = body.get("create_spec") or body
    library_item_id = str(create_spec.get("library_item_id") or create_spec.get("item_id") or "")
    if not library_item_id:
        from app.vsphere.errors import invalid_argument

        raise invalid_argument("create_spec.library_item_id is required")
    return await content.create_update_session(database, library_item_id=library_item_id)


@router.get("/api/content/library/item/update-session/{session_id}")
async def get_update_session(
    session_id: str,
    database: Database = Depends(get_database),
    _: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
    return await content.get_update_session(database, session_id)


@router.post("/api/content/library/item/update-session/{session_id}/file")
async def add_update_session_file(
    session_id: str,
    body: dict[str, Any],
    database: Database = Depends(get_database),
    _: SessionInfo = Depends(require_privilege("ContentLibrary.AddLibraryItem")),
) -> dict[str, Any]:
    file_spec = body.get("file_spec") or body
    return await content.add_update_session_file(
        database,
        session_id,
        name=str(file_spec.get("name") or "upload.bin"),
        source_type=str(file_spec.get("source_type") or "PUSH"),
        size=int(file_spec.get("size") or 0),
        content=str(file_spec.get("content") or ""),
    )


@router.post("/api/content/library/item/update-session/{session_id}")
async def complete_update_session(
    session_id: str,
    action: str = Query("complete"),
    database: Database = Depends(get_database),
    _: SessionInfo = Depends(require_privilege("ContentLibrary.AddLibraryItem")),
) -> None:
    del action
    await content.complete_update_session(database, session_id)


@router.post("/api/content/library/item/download-session")
async def create_download_session(
    body: dict[str, Any],
    database: Database = Depends(get_database),
    _: SessionInfo = Depends(require_read),
) -> str:
    create_spec = body.get("create_spec") or body
    library_item_id = str(create_spec.get("library_item_id") or create_spec.get("item_id") or "")
    if not library_item_id:
        from app.vsphere.errors import invalid_argument

        raise invalid_argument("create_spec.library_item_id is required")
    return await content.create_download_session(database, library_item_id=library_item_id)


@router.get("/api/content/library/item/download-session/{session_id}")
async def get_download_session(
    session_id: str,
    database: Database = Depends(get_database),
    _: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
    return await content.get_download_session(database, session_id)


@router.get("/api/content/library/item/download-session/{session_id}/file")
async def list_download_session_files(
    session_id: str,
    database: Database = Depends(get_database),
    _: SessionInfo = Depends(require_read),
) -> list[dict[str, Any]]:
    return await content.list_download_session_files(database, session_id)


@router.get("/api/content/library/item/{library_item_id}")
async def get_item(
    library_item_id: str,
    database: Database = Depends(get_database),
    _: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
    return await content.get_library_item(database, library_item_id)


@router.delete("/api/content/library/item/{library_item_id}")
async def delete_item(
    library_item_id: str,
    database: Database = Depends(get_database),
    _: SessionInfo = Depends(require_privilege("ContentLibrary.AddLibraryItem")),
) -> Response:
    await content.delete_library_item(database, library_item_id)
    return Response(status_code=204)


@router.get("/api/content/library/{library_id}")
async def get_library(
    library_id: str,
    database: Database = Depends(get_database),
    _: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
    return await content.get_library(database, library_id)


@router.get("/api/content/local-library/{library_id}")
async def get_local_library(
    library_id: str,
    database: Database = Depends(get_database),
    _: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
    info = await content.get_library(database, library_id)
    if str(info.get("type") or "").upper() not in {"LOCAL", ""}:
        from app.vsphere.errors import not_found

        raise not_found(f"Local library {library_id} not found")
    return info


@router.delete("/api/content/local-library/{library_id}")
async def delete_local_library(
    library_id: str,
    database: Database = Depends(get_database),
    _: SessionInfo = Depends(require_privilege("ContentLibrary.CreateLocalLibrary")),
) -> Response:
    await content.delete_library(database, library_id)
    return Response(status_code=204)


@router.post("/api/vcenter/ovf/library-item/{item_id}")
async def deploy_ovf(
    item_id: str,
    body: dict[str, Any],
    database: Database = Depends(get_database),
    _: SessionInfo = Depends(require_privilege("VirtualMachine.Provisioning.DeployTemplate")),
) -> dict[str, Any]:
    target = body.get("target") or {}
    deployment = body.get("deployment_spec") or body
    folder = (
        target.get("folder_id")
        or target.get("folder")
        or deployment.get("folder")
        or "group-v23"
    )
    host = target.get("host_id") or target.get("host") or "host-11"
    datastore = (
        target.get("datastore_id")
        or target.get("datastore")
        or deployment.get("datastore")
        or "datastore-31"
    )
    resource_pool = (
        target.get("resource_pool_id")
        or target.get("resource_pool")
        or deployment.get("resource_pool")
    )
    moid, task_id = await content.deploy_ovf_from_library(
        database,
        item_id=item_id,
        name=str(deployment.get("name") or f"ovf-{item_id[-6:]}"),
        folder=str(folder),
        host=str(host),
        datastore=str(datastore),
        resource_pool=str(resource_pool) if resource_pool else None,
    )
    return {"resource_id": {"id": moid, "type": "VirtualMachine"}, "task": task_id}


@router.get("/api/vcenter/storage/policies")
async def storage_policies(
    database: Database = Depends(get_database),
    _: SessionInfo = Depends(require_read),
) -> list[dict[str, Any]]:
    payload = await api_state.get_payload(database, "GET", "/api/vcenter/storage/policies")
    if isinstance(payload, list):
        return payload
    return []
