from __future__ import annotations

from typing import TYPE_CHECKING, Optional

if TYPE_CHECKING:
    from mockmesh.storage.manager import StorageManager

_RAW_KEY = "_raw_bytes"


def handle_gcs(
    sm: "StorageManager",
    bucket: str,
    object_name: str,
    method: str,
    body: bytes,
    tpl: dict,
    url: str = "",
) -> Optional[dict]:
    if method in ("PUT", "POST") and object_name:
        ct     = "application/octet-stream"
        stored = sm.gcs_put(bucket, object_name, body, ct)
        base   = dict(tpl.get("insert", {}))
        base.update({
            "kind":      "storage#object",
            "name":      object_name,
            "bucket":    bucket,
            "size":      str(len(body)),
            "etag":      stored.get("ETag", "mock-etag").strip('"'),
            "selfLink":  f"https://www.googleapis.com/storage/v1/b/{bucket}/o/{object_name}",
            "mediaLink": (
                f"https://storage.googleapis.com/download/storage/v1"
                f"/b/{bucket}/o/{object_name}?alt=media"
            ),
        })
        return base

    if method == "GET" and object_name:
        obj = sm.gcs_get(bucket, object_name)
        if obj:
            if "alt=media" in url:
                return {_RAW_KEY: obj["Body"],
                        "_content_type": obj.get("ContentType", "application/octet-stream")}
            base = dict(tpl.get("get", {}))
            base.update({
                "kind":        "storage#object",
                "name":        object_name,
                "bucket":      bucket,
                "size":        str(obj.get("ContentLength", 0)),
                "contentType": obj.get("ContentType", "application/octet-stream"),
                "etag":        obj.get("ETag", "mock-etag").strip('"'),
            })
            return base
        return None

    if method == "GET" and not object_name:
        items  = sm.gcs_list(bucket, "")
        result = dict(tpl.get("list", {"kind": "storage#objects", "items": []}))
        result["items"] = [
            {
                "kind":   "storage#object",
                "name":   o.get("Key", o.get("key", "?")),
                "bucket": bucket,
                "size":   str(o.get("Size", 0)),
            }
            for o in items
        ]
        return result

    if method == "DELETE" and object_name:
        sm.gcs_delete(bucket, object_name)
        return {}

    return None


def handle_gcs_bucket(
    sm: "StorageManager",
    bucket: str,
    method: str,
    tpl: dict,
) -> Optional[dict]:
    if method in ("POST", "PUT"):
        resp = dict(tpl.get("buckets_insert", {}))
        resp.update({"name": bucket, "id": bucket})
        return resp

    if method == "GET":
        resp = dict(tpl.get("buckets_get", {}))
        resp["name"] = bucket
        return resp

    if method == "DELETE":
        return {}

    return dict(tpl.get("buckets_list", {"kind": "storage#buckets", "items": []}))
