"""Generic runtime host for the external.entity_ingest primitive.

One shared adapter (p2hs-entity-ingest.mjs) plus one thin route file per
entity_ingest_binding the project has installed, at the exact `forward_path`
Core registered the webhook subscription against. Entity-agnostic and
pack-agnostic by design: content-ingest is the first caller, but any future
pack with its own entity_ingest_bindings installs through this same function,
unmodified.

Each binding dict must supply: pack_slug, provider, forward_path (all already
resolved from the pack's stamped composition — see
feature_packs/service.py's webhook_setup loop, which is also where the
matching Core-side webhook subscription + forward_secret propagation happens;
see WEBHOOK_SECRET_ENV_KEY for the exact env var name that secret lands in).
"""
from __future__ import annotations

import posixpath
from pathlib import Path
from typing import TypedDict

_PAGES_TYPES = frozenset({"html", "react_app", "nuxt_app"})
_RUNTIME = Path(__file__).with_name("runtime")


class EntityIngestBinding(TypedDict):
    pack_slug: str
    provider: str
    forward_path: str


def webhook_secret_env_key(pack_slug: str, provider: str) -> str:
    """Must match feature_packs/service.py's env_key computation exactly —
    that's the function that actually writes this secret into the project's
    encrypted env vars after provisioning the Cloud webhook subscription."""
    parts = [part.upper() for part in (pack_slug, provider) if part]
    return ("P2HS_WEBHOOK_SECRET_" + "_".join(parts)).replace("-", "_")


def _route_relative_path(forward_path: str, *, lib_dir: str) -> str:
    """Relative import from the route file's own directory (one level under
    forward_path's parent, since Pages/Nuxt route files sit at exactly
    forward_path's location) to `{lib_dir}/p2hs-entity-ingest.mjs`."""
    route_dir = posixpath.dirname(forward_path.strip("/"))
    depth = len(route_dir.split("/")) if route_dir else 0
    prefix = "../" * depth if depth else "./"
    return f"{prefix}{lib_dir}/p2hs-entity-ingest.mjs"


def _fill(content: str, *, pack_slug: str, provider: str, forward_path: str, lib_dir: str) -> str:
    return (
        content.replace("__P2HS_ENTITY_INGEST_PACK_SLUG__", pack_slug)
        .replace("__P2HS_ENTITY_INGEST_PROVIDER__", provider)
        .replace("__P2HS_ENTITY_INGEST_SECRET_ENV_KEY__", webhook_secret_env_key(pack_slug, provider))
        .replace("__P2HS_ENTITY_INGEST_LIB_IMPORT__", _route_relative_path(forward_path, lib_dir=lib_dir))
    )


def entity_ingest_adapter_files(
    project_type: str, bindings: list[EntityIngestBinding]
) -> dict[str, str]:
    if project_type not in _PAGES_TYPES or not bindings:
        return {}

    shared = (_RUNTIME / "p2hs-entity-ingest.mjs").read_text(encoding="utf-8")
    pages_template = (_RUNTIME / "entity-ingest-webhook-pages-fn.js").read_text(encoding="utf-8")
    nuxt_template = (_RUNTIME / "entity-ingest-webhook-route.ts").read_text(encoding="utf-8")

    files: dict[str, str] = {
        "functions/_lib/p2hs-entity-ingest.mjs": shared,
    }
    if project_type == "nuxt_app":
        files["server/utils/p2hs-entity-ingest.mjs"] = shared

    for binding in bindings:
        forward_path = binding["forward_path"].strip("/")
        pages_path = f"functions/{forward_path}.js"
        files[pages_path] = _fill(
            pages_template,
            pack_slug=binding["pack_slug"],
            provider=binding["provider"],
            forward_path=binding["forward_path"],
            lib_dir="_lib",
        )
        if project_type == "nuxt_app":
            nuxt_path = f"server/{forward_path}.post.ts"
            files[nuxt_path] = _fill(
                nuxt_template,
                pack_slug=binding["pack_slug"],
                provider=binding["provider"],
                forward_path=binding["forward_path"],
                lib_dir="utils",
            )

    return files
