#!/usr/bin/env python3
"""Fail closed if the delivery encoder's supply chain or licence position drifts.

Three things must stay true or cinemaOS must not ship:
  1. Every pinned source in PROVENANCE.json still declares a licence we may
     bundle in a proprietary app (no GPL).
  2. The built helper reports no --enable-gpl, is arm64, and is executable.
  3. Every licence file the provenance references actually exists, because the
     LGPL obligation is to ship those texts, not to intend to.
"""

from __future__ import annotations

import json
import subprocess
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parent
PROVENANCE = ROOT / "PROVENANCE.json"
HELPER = ROOT / "dist" / "MomentumTranscodeHelper"

# Licences we may bundle inside a closed-source application. Anything outside
# this set is a licence incident, not a build warning.
ALLOWED_LICENCES = {
    "LGPL-2.1-or-later",
    "LGPL-2.0-or-later",
    "LGPL-3.0-or-later",
    "BSD-2-Clause",
    "BSD-3-Clause",
    "MIT",
    "ISC",
    "Apache-2.0",
}

# Matched as whole identifiers, never as substrings: "LGPL-2.0-or-later"
# contains "GPL-2.0-or-later", and the Lesser GPL is exactly what we are
# allowed to bundle.
FORBIDDEN_LICENCES = frozenset({
    "GPL-2.0-only", "GPL-2.0-or-later", "GPL-3.0-only", "GPL-3.0-or-later",
    "AGPL-3.0-only", "AGPL-3.0-or-later",
})


def fail(message: str) -> None:
    raise SystemExit(f"Transcode helper provenance failure: {message}")


def main() -> None:
    if not PROVENANCE.is_file():
        fail(f"missing {PROVENANCE}")

    try:
        provenance = json.loads(PROVENANCE.read_text())
    except json.JSONDecodeError as error:
        fail(f"PROVENANCE.json is not valid JSON: {error}")

    sources = provenance.get("sources") or []
    if not sources:
        fail("PROVENANCE.json declares no sources")

    for source in sources:
        name = source.get("name", "<unnamed>")
        licence = source.get("license", "")

        if licence in FORBIDDEN_LICENCES:
            fail(
                f"{name} is licensed {licence}. A GPL component cannot ship inside "
                f"proprietary cinemaOS."
            )
        if licence not in ALLOWED_LICENCES:
            fail(f"{name} declares an unreviewed licence: {licence!r}")

        for digest in ("sha256",):
            value = source.get(digest, "")
            if len(value) != 64 or any(c not in "0123456789abcdef" for c in value):
                fail(f"{name} has no valid pinned {digest}")

        licence_file = source.get("licenseFile")
        if not licence_file:
            fail(f"{name} names no licence file, so the bundle cannot satisfy the LGPL")
        if not (ROOT / licence_file).is_file():
            fail(f"{name} references a missing licence file: {licence_file}")

    position = provenance.get("licensePosition") or {}
    if position.get("gplComponentsPresent") is not False:
        fail("PROVENANCE.json must assert gplComponentsPresent = false")
    if "--enable-gpl" in (position.get("configureFlags") or []):
        fail("configure flags include --enable-gpl")

    # The built artefact, when present, must agree with the declaration. A CI
    # host that has not built the helper yet is allowed; a host that HAS built
    # it and got a GPL binary is not.
    if HELPER.is_file():
        try:
            version = subprocess.run(
                [str(HELPER), "-version"],
                capture_output=True, timeout=30, check=False,
            ).stdout.decode(errors="replace")
        except OSError as error:
            fail(f"built helper is not runnable: {error}")

        if "--enable-gpl" in version:
            fail(
                "the built helper reports --enable-gpl. Rebuild without GPL "
                "components before shipping."
            )

        archs = subprocess.run(
            ["lipo", "-archs", str(HELPER)],
            capture_output=True, timeout=30, check=False,
        ).stdout.decode().strip()
        if archs != "arm64":
            fail(f"built helper must be pure arm64 (found: {archs!r})")

    known_gaps = provenance.get("knownGaps") or []
    for gap in known_gaps:
        if not gap.get("resolution"):
            fail(f"known gap {gap.get('format')!r} states no resolution")

    print(
        f"✓ transcode helper provenance: {len(sources)} pinned sources, "
        f"no GPL components, {len(known_gaps)} documented gaps"
    )


if __name__ == "__main__":
    sys.exit(main())
