#!/usr/bin/env python3
"""Run Factory from an authorized private GitHub ref and write a result bundle."""
from __future__ import annotations

import json
import os
import re
import shutil
import subprocess
import sys
from pathlib import Path

from adw_modules import repository_registry, result_mailbox

WORKSPACE = Path("/workspace/repo")
DEPENDENCY_SEEDS = Path("/opt/factory-dependencies")
DEPENDENCY_STORE = Path("/workspace/.pnpm-store")
DEPENDENCY_VERIFICATION_CACHE = Path.home() / ".cache/pnpm/lockfile-verified.jsonl"
EXECUTION = re.compile(r"refs/heads/factory-exec/[0-9a-f]{24}")
RESULT = re.compile(r"refs/heads/factory-result/[0-9a-f]{24}")


def call(args: list[str], *, cwd: Path | None = None, check=True):
    result = subprocess.run(args, cwd=cwd, check=False)
    if check and result.returncode:
        raise RuntimeError(f"{args[0]} exited {result.returncode}")
    return result


def provision_dependencies(repository_id: str) -> None:
    package_json = WORKSPACE / "package.json"
    if not package_json.is_file():
        return
    package = json.loads(package_json.read_text())
    package_manager = package.get("packageManager")
    if not isinstance(package_manager, str) or not package_manager.startswith("pnpm@"):
        return
    seed = DEPENDENCY_SEEDS / repository_id / "pnpm-store"
    verification_seed = DEPENDENCY_SEEDS / repository_id / "pnpm-cache/lockfile-verified.jsonl"
    if not seed.is_dir() or not verification_seed.is_file():
        raise RuntimeError(f"approved dependency cache is unavailable for repository {repository_id}")
    store = DEPENDENCY_STORE
    if store.exists():
        shutil.rmtree(store)
    shutil.copytree(seed, store, symlinks=True)
    verification_cache = DEPENDENCY_VERIFICATION_CACHE
    verification_cache.parent.mkdir(parents=True, exist_ok=True)
    shutil.copy2(verification_seed, verification_cache)
    os.environ["PNPM_STORE_DIR"] = str(store)
    os.environ["XDG_CACHE_HOME"] = str(verification_cache.parent.parent)
    call(
        [
            "/usr/local/bin/pnpm",
            "install",
            "--frozen-lockfile",
            "--offline",
            "--fetch-retries",
            "0",
            "--store-dir",
            str(store),
        ],
        cwd=WORKSPACE,
    )


def main() -> int:
    repository_id = os.environ["FACTORY_REPOSITORY_ID"]
    envelope = repository_registry.verify_envelope(
        os.environ["FACTORY_ATTEMPT_ENVELOPE"],
        repository_registry.load(),
        Path("/home/factory/attempt-signing-public-key.pem").read_bytes(),
    )
    if envelope.repository_id != repository_id:
        raise RuntimeError("attempt envelope repository ID does not match workload")
    if envelope.credential_handle != os.environ["FACTORY_CREDENTIAL_HANDLE"]:
        raise RuntimeError("attempt envelope credential does not match workload")
    repository = repository_registry.resolve(repository_registry.load(), repository_id, envelope.workflow)
    execution = os.environ["FACTORY_EXECUTION_REF"]
    result_ref = os.environ["FACTORY_RESULT_REF"]
    if not EXECUTION.fullmatch(execution) or not RESULT.fullmatch(result_ref):
        raise RuntimeError("invalid transport ref")
    invocation = json.loads(os.environ["FACTORY_INVOCATION_JSON"])
    if not isinstance(invocation, list) or not invocation or any(not isinstance(value, str) for value in invocation):
        raise RuntimeError("invalid Factory invocation")
    upload_data = json.loads(os.environ["FACTORY_RESULT_UPLOAD_JSON"])
    if not isinstance(upload_data, dict) or set(upload_data) != {"url", "token", "ca_pem"} or any(not isinstance(value, str) for value in upload_data.values()):
        raise RuntimeError("invalid Factory result upload target")
    upload = result_mailbox.UploadTarget(**upload_data)
    attempt_id = execution.removeprefix("refs/heads/factory-exec/")
    parsed_upload = result_mailbox.validate_target(upload, attempt_id)
    os.environ["NO_PROXY"] = f"127.0.0.1,{parsed_upload.hostname}"
    os.environ["no_proxy"] = os.environ["NO_PROXY"]
    if (
        envelope.attempt_id != attempt_id
        or envelope.execution_ref != execution
        or envelope.result_ref != result_ref
        or envelope.invocation_sha256 != repository_registry.invocation_sha256(invocation)
        or envelope.upload_sha256 != result_mailbox.target_sha256(upload)
    ):
        raise RuntimeError("attempt envelope does not match workload transport")
    branch = execution.removeprefix("refs/heads/")
    os.environ["GIT_SSH_COMMAND"] = "/usr/bin/ssh -o HostName=ssh.github.com -p 443 -o HostKeyAlias=github.com -o ProxyCommand='/bin/nc -X connect -x overdeck-factory-egress:8888 %h %p' -i /home/factory/.ssh/id_ed25519 -o IdentitiesOnly=yes -o StrictHostKeyChecking=yes -o UserKnownHostsFile=/home/factory/.ssh/known_hosts"
    clone_url = f"git@github.com:{repository.github_owner}/{repository.github_repository}.git"
    call(["/usr/bin/git", "clone", "--single-branch", "--branch", branch, "--", clone_url, str(WORKSPACE)])
    input_commit = subprocess.check_output(["/usr/bin/git", "rev-parse", "HEAD^{commit}"], cwd=WORKSPACE, text=True).strip()
    if input_commit != envelope.input_commit:
        raise RuntimeError("execution ref does not resolve to the authorized input commit")
    call(["/usr/bin/git", "config", "user.name", "Overdeck Factory"], cwd=WORKSPACE)
    call(["/usr/bin/git", "config", "user.email", "factory@overdeck.invalid"], cwd=WORKSPACE)
    provision_dependencies(repository_id)
    factory = call(["/opt/factory/bin/factory", "--repo", str(WORKSPACE), *invocation], cwd=WORKSPACE, check=False)
    call(["/usr/bin/git", "add", "-A"], cwd=WORKSPACE)
    call(["/usr/bin/git", "commit", "--allow-empty", "-m", "Capture Factory Kubernetes result"], cwd=WORKSPACE)
    result_dir = Path("/result")
    result_dir.mkdir(exist_ok=True)
    bundle = result_dir / "result.bundle"
    temporary = result_dir / "result.bundle.tmp"
    call(["/usr/bin/git", "bundle", "create", str(temporary), "HEAD", f"^{input_commit}"], cwd=WORKSPACE)
    os.replace(temporary, bundle)
    marker = result_dir / "complete.tmp"
    marker.write_bytes(b"")
    os.replace(marker, result_dir / "complete")
    return factory.returncode


if __name__ == "__main__":
    try:
        raise SystemExit(main())
    except Exception as exc:
        print(f"factory-kubernetes-worker: {exc}", file=sys.stderr)
        raise SystemExit(1)
