"""Private provenance for Starter-First Composition canaries.

The manifest is control-plane evidence. It is never a customer-facing runtime
contract and must stay under the ignored ``.p2hs`` directory when materialized.
"""

from __future__ import annotations

import hashlib
import json
from pathlib import Path
from typing import Any


def build_assembly_manifest(
    generation_plan: dict[str, Any],
    *,
    archetype_id: str,
    archetype_source: str,
    starter_contracts: list[dict[str, str]],
    feature_packs: list[dict[str, str]],
    app_blocks: list[dict[str, str]],
    cloud_bindings: list[dict[str, str]],
    generated_remainder: list[str],
) -> dict[str, Any]:
    """Return deterministic assembled/reused/generated provenance."""
    plan_hash = str((generation_plan.get("provenance") or {}).get("plan_hash") or "")
    payload: dict[str, Any] = {
        "schema_version": "assembly_manifest.v1",
        "generation_plan_hash": plan_hash,
        "archetype": {"id": archetype_id, "source": archetype_source},
        "starter_contracts": starter_contracts,
        "feature_packs": feature_packs,
        "app_blocks": app_blocks,
        "cloud_bindings": cloud_bindings,
        "generated_remainder": {
            "files": sorted(set(generated_remainder)),
            "classification": "generated",
        },
        "provenance": {
            "starter_catalog_version": "catalog.v1",
            "feature_pack_catalog_version": "feature-packs.v1",
            "app_block_registry_version": "registry.v1",
        },
    }
    canonical = json.dumps(payload, sort_keys=True, separators=(",", ":"))
    payload["assembly_manifest_hash"] = hashlib.sha256(canonical.encode()).hexdigest()
    return payload


def write_private_assembly_manifest(repo_path: str | Path, manifest: dict[str, Any]) -> Path:
    target = Path(repo_path) / ".p2hs" / "assembly-manifest.json"
    target.parent.mkdir(parents=True, exist_ok=True)
    target.write_text(json.dumps(manifest, indent=2) + "\n", encoding="utf-8")
    return target


__all__ = ["build_assembly_manifest", "write_private_assembly_manifest"]
