"""Ownership record for files a Hosting Profile is allowed to regenerate.

Customer edits to a previously generated file are conflicts. They are reported
and left in place. Files with no ownership record yet are adopted, which is
how an existing Pages or W4P repository receives the manifest the first time.
"""
from __future__ import annotations

import hashlib
import json
from pathlib import Path

MANIFEST_REL = "p2hs/hosting-managed-files.json"


def content_hash(text: str) -> str:
    return hashlib.sha256(text.encode("utf-8")).hexdigest()


def classify_managed_file(
    existing: str | None,
    recorded_hash: str | None,
    new_content: str,
) -> str:
    """Return create, unchanged, regenerate, or conflict."""

    if existing is None:
        return "create"
    current_hash = content_hash(existing)
    if current_hash == content_hash(new_content):
        return "unchanged"
    if recorded_hash is None or recorded_hash == current_hash:
        return "regenerate"
    return "conflict"


def load_manifest(root: Path) -> dict[str, dict]:
    path = root / MANIFEST_REL
    if not path.is_file():
        return {}
    payload = json.loads(path.read_text(encoding="utf-8"))
    files = payload.get("files")
    if not isinstance(files, dict):
        return {}
    return {str(name): dict(entry) for name, entry in files.items() if isinstance(entry, dict)}


def save_manifest(root: Path, files: dict[str, dict]) -> None:
    path = root / MANIFEST_REL
    path.parent.mkdir(parents=True, exist_ok=True)
    payload = {
        "schema_version": 1,
        "ownership": "p2hs",
        "files": files,
    }
    path.write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8", newline="\n")


def plan_managed_updates(root: Path, files: dict[str, str]) -> list[tuple[str, str]]:
    """Return (relative path, action) without writing."""

    manifest = load_manifest(root)
    planned: list[tuple[str, str]] = []
    for name, content in files.items():
        target = root / name
        existing = target.read_text(encoding="utf-8") if target.is_file() else None
        recorded = (manifest.get(name) or {}).get("sha256")
        planned.append((name, classify_managed_file(existing, recorded, content)))
    return planned
