from __future__ import annotations

import uuid
from typing import TYPE_CHECKING, Optional

from mockmesh.interceptors.azure.utils import _enc, _get_body, _safe_json
from mockmesh.interceptors.responses import FakeAzureResponse

if TYPE_CHECKING:
    from mockmesh.storage.manager import StorageManager

_JSON_HDR = {"Content-Type": "application/json"}


def handle_keyvault(
    sm: "StorageManager", parsed: dict, request: object,
    method: str, url: str, tpl: dict,
) -> Optional[FakeAzureResponse]:
    secret_name = parsed["container"]
    body_data   = _safe_json(_get_body(request))
    vault_host  = tpl.get("vault_host", "https://mock-vault.vault.azure.net")
    def_attrs   = dict(tpl.get("default_attributes", {}))

    if method in ("PUT", "PATCH") and secret_name:
        version    = str(uuid.uuid4()).replace("-", "")[:32]
        secret_val = body_data.get("value", "mock-secret-value")
        full_id    = vault_host + "/secrets/" + secret_name + "/" + version
        stored     = {"id": full_id, "value": secret_val, "version": version, "attributes": def_attrs}
        sm.nosql.put("kv_secrets", secret_name, stored)
        resp = dict(tpl.get(method, tpl.get("PUT", {})))
        resp.update({"id": full_id, "value": secret_val, "attributes": stored["attributes"]})
        return FakeAzureResponse(200, _JSON_HDR, _enc(resp))

    if method == "GET" and secret_name:
        item = sm.nosql.get("kv_secrets", secret_name)
        if item:
            resp = dict(tpl.get("GET", {}))
            resp.update({
                "id":         item.get("id", vault_host + "/secrets/" + secret_name),
                "value":      item["value"],
                "attributes": item.get("attributes", resp.get("attributes", def_attrs)),
            })
            return FakeAzureResponse(200, _JSON_HDR, _enc(resp))
        err = dict(tpl.get("NOT_FOUND", {"error": {"code": "SecretNotFound", "message": "Secret not found"}}))
        if "error" in err:
            err["error"] = dict(err["error"])
            err["error"]["message"] = "Secret " + repr(secret_name) + " not found"
        return FakeAzureResponse(404, _JSON_HDR, _enc(err))

    if method == "GET" and not secret_name:
        items    = sm.nosql.list("kv_secrets")
        list_tpl = dict(tpl.get("GET_list", {"value": [], "nextLink": None}))
        list_tpl["value"] = [
            {"id": r["value"].get("id", vault_host + "/secrets/" + r["key"]),
             "attributes": r["value"].get("attributes", dict(def_attrs))}
            for r in items
        ]
        return FakeAzureResponse(200, _JSON_HDR, _enc(list_tpl))

    if method == "DELETE" and secret_name:
        item    = sm.nosql.get("kv_secrets", secret_name)
        sm.nosql.delete("kv_secrets", secret_name)
        del_tpl = dict(tpl.get("DELETE", {}))
        full_id = (item or {}).get("id", vault_host + "/secrets/" + secret_name)
        del_tpl.update({"id": full_id, "recoveryId": vault_host + "/deletedsecrets/" + secret_name})
        return FakeAzureResponse(200, _JSON_HDR, _enc(del_tpl))

    return None
