from __future__ import annotations

import json
import os
import stat
import subprocess
from pathlib import Path


ROOT = Path(__file__).resolve().parents[2]
HELPER = ROOT / "subrouter/bin/migration-provision"


def _fake_subrouter(tmp_path: Path) -> tuple[Path, Path]:
    log = tmp_path / "calls.log"
    fake = tmp_path / "subrouter"
    fake.write_text(
        """#!/usr/bin/env bash
set -euo pipefail
printf '%s\\n' \"$*\" >> \"${FAKE_LOG:?}\"
case \"${1:-} ${2:-}\" in
  'authority-account login')
    printf '%s\\n' 'Authority account login: complete'
    ;;
  'authority-account remove')
    printf '%s\\n' 'Authority account: removed'
    ;;
  'authority-route create')
    out=''
    while (($#)); do
      case \"$1\" in
        --route-id-file) out=$2; shift 2 ;;
        *) shift ;;
      esac
    done
    [[ -n \"$out\" ]]
    printf '%s\\n' 'routefixture1234567890' > \"$out\"
    chmod 0600 \"$out\"
    ;;
  'authority-route remove')
    ;;
  'authority-grant create')
    if [[ ${FAKE_FAIL_GRANT:-0} == 1 ]]; then exit 41; fi
    out=''
    while (($#)); do
      case \"$1\" in
        --proxy-key-file) out=$2; shift 2 ;;
        *) shift ;;
      esac
    done
    [[ -n \"$out\" ]]
    printf '%s\\n' 'synthetic-proxy-key-never-print' > \"$out\"
    chmod 0600 \"$out\"
    ;;
  *) exit 42 ;;
esac
""",
        encoding="utf-8",
    )
    fake.chmod(0o755)
    return fake, log


def _run(tmp_path: Path, provider: str, *, fail_grant: bool = False) -> tuple[subprocess.CompletedProcess[str], Path, Path]:
    fake, log = _fake_subrouter(tmp_path)
    test_root = tmp_path / "root"
    test_root.mkdir(mode=0o700)
    output = tmp_path / "material"
    output.mkdir(mode=0o700)
    env = {
        **os.environ,
        "OVERDECK_SUBROUTER_MIGRATION_TEST_ROOT": str(test_root),
        "OVERDECK_SUBROUTER_BIN": str(fake),
        "FAKE_LOG": str(log),
        "FAKE_FAIL_GRANT": "1" if fail_grant else "0",
    }
    result = subprocess.run(
        [
            str(HELPER),
            "provision",
            "--run-id",
            f"fixture-{provider}",
            "--provider",
            provider,
            "--account-id",
            f"fixture-{provider}",
            "--output-dir",
            str(output),
            "--ttl-seconds",
            "600",
        ],
        env=env,
        text=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        check=False,
    )
    return result, output, log


def test_migration_provision_success_is_protected_and_bounded(tmp_path: Path) -> None:
    for provider in ("codex", "claude"):
        provider_root = tmp_path / provider
        provider_root.mkdir()
        result, output, log = _run(provider_root, provider)
        assert result.returncode == 0, result.stderr
        assert "synthetic-proxy-key-never-print" not in result.stdout + result.stderr
        payload = json.loads(result.stdout.splitlines()[-1])
        assert payload["status"] == "provisioned"
        assert payload["grant_expires_at"].endswith("Z")
        route = output / "route.id"
        key = output / "proxy.key"
        assert route.read_text(encoding="utf-8").strip() == "routefixture1234567890"
        assert key.read_text(encoding="utf-8").strip() == "synthetic-proxy-key-never-print"
        for path in (route, key):
            info = path.lstat()
            assert stat.S_ISREG(info.st_mode)
            assert stat.S_IMODE(info.st_mode) == 0o600
            assert info.st_nlink == 1
        calls = log.read_text(encoding="utf-8")
        assert f"authority-account login --state-dir" in calls
        assert f"--provider {provider} --account-id fixture-{provider}" in calls
        assert ("--device-auth" in calls) is (provider == "codex")
        assert "authority-route create" in calls
        assert "--enabled" in calls
        assert "--audience workstation" in calls


def test_migration_provision_grant_failure_compensates_account_and_route(tmp_path: Path) -> None:
    result, output, log = _run(tmp_path, "claude", fail_grant=True)
    assert result.returncode != 0
    assert not (output / "route.id").exists()
    assert not (output / "proxy.key").exists()
    calls = log.read_text(encoding="utf-8")
    assert "authority-route remove" in calls
    assert "authority-account remove" in calls
    assert "synthetic-proxy-key-never-print" not in result.stdout + result.stderr


def test_migration_provision_service_environment_has_fixed_system_path() -> None:
    source = HELPER.read_text(encoding="utf-8")
    assert (
        "SERVICE_PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
        in source
    )
    assert 'PATH="$SERVICE_PATH" HOME="$STATE_DIR/home"' in source
