from __future__ import annotations

import hashlib
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
VERSION = "v0.39.4-dev Consolidated"
PROJECT = "HRPAY-BMD-20260911-01"

EXCLUDED_DIRS = {".venv", "__pycache__", "backups"}
EXCLUDED_SUFFIXES = {".pyc"}
RUNTIME_FILES = {".env.local", "LOCAL-UAT-SMOKE-RESULT.txt", "MIGRATION-FREEZE-RESULT.txt"}


def package_files() -> list[Path]:
    files: list[Path] = []
    for path in ROOT.rglob("*"):
        if not path.is_file():
            continue
        rel = path.relative_to(ROOT)
        if any(part in EXCLUDED_DIRS for part in rel.parts):
            continue
        if path.suffix.lower() in EXCLUDED_SUFFIXES:
            continue
        if path.name in RUNTIME_FILES:
            continue
        files.append(path)
    return sorted(files, key=lambda p: p.relative_to(ROOT).as_posix().lower())


def sha256(path: Path) -> str:
    h = hashlib.sha256()
    with path.open("rb") as f:
        for chunk in iter(lambda: f.read(1024 * 1024), b""):
            h.update(chunk)
    return h.hexdigest()


def main() -> None:
    manifest_path = ROOT / "PACKAGE-CONTENTS.txt"
    sha_path = ROOT / "SHA256SUMS.txt"

    # Avoid cyclic metadata: PACKAGE-CONTENTS excludes itself and SHA256SUMS.
    files = package_files()
    manifest_members = [
        p for p in files if p not in {manifest_path, sha_path}
    ]
    lines = [
        f"HR & Payroll UAT Remediation {VERSION} - Package Contents",
        f"Project: {PROJECT}",
        "",
        "Integrity note: PACKAGE-CONTENTS.txt intentionally excludes itself and SHA256SUMS.txt.",
        "",
    ]
    for path in manifest_members:
        rel = path.relative_to(ROOT).as_posix()
        lines.append(f"{rel}\t{path.stat().st_size} bytes")
    manifest_path.write_text("\n".join(lines) + "\n", encoding="utf-8")

    # Hash every shipped file except SHA256SUMS itself; this includes PACKAGE-CONTENTS.
    files = package_files()
    hash_members = [p for p in files if p != sha_path]
    sha_lines = [
        f"{sha256(path)}  ./{path.relative_to(ROOT).as_posix()}"
        for path in hash_members
    ]
    sha_path.write_text("\n".join(sha_lines) + "\n", encoding="utf-8")

    print(f"PACKAGE-CONTENTS entries: {len(manifest_members)}")
    print(f"SHA256SUMS entries: {len(hash_members)}")
    print("RESULT: PASS")


if __name__ == "__main__":
    main()
