"""Phase 3 release runner: parse .env, invoke `bash .release/release.sh`
with CF_API_KEY injected. Captures stdout/stderr; returns a structured
ReleaseResult. Does not push to git (the detector handles that separately).
"""
import os
import subprocess
from dataclasses import dataclass
from pathlib import Path

RELEASE_TIMEOUT_SECONDS = 600  # 10 minutes


@dataclass(frozen=True)
class ReleaseResult:
    success: bool
    stdout: str
    stderr: str
    returncode: int


def parse_dotenv(path: Path) -> dict[str, str]:
    out: dict[str, str] = {}
    for raw_line in path.read_text(encoding="utf-8").splitlines():
        line = raw_line.strip()
        if not line or line.startswith("#"):
            continue
        if line.startswith("export "):
            line = line[len("export "):].lstrip()
        if "=" not in line:
            continue
        key, _, value = line.partition("=")
        key = key.strip()
        value = value.strip()
        if (value.startswith('"') and value.endswith('"')) or (value.startswith("'") and value.endswith("'")):
            value = value[1:-1]
        out[key] = value
    return out


def run_release(repo_root: Path) -> ReleaseResult:
    script = repo_root / ".release" / "release.sh"
    if not script.exists():
        raise FileNotFoundError(f"{script} does not exist")
    dotenv = repo_root / ".env"
    if not dotenv.exists():
        raise FileNotFoundError(f"{dotenv} does not exist")
    env_vars = parse_dotenv(dotenv)
    if "CF_API_KEY" not in env_vars:
        raise KeyError("CF_API_KEY")
    env = {**os.environ, "CF_API_KEY": env_vars["CF_API_KEY"]}
    proc = subprocess.run(
        ["bash", str(script)],
        cwd=str(repo_root),
        env=env,
        capture_output=True, text=True,
        timeout=RELEASE_TIMEOUT_SECONDS, check=False,
    )
    return ReleaseResult(
        success=(proc.returncode == 0),
        stdout=proc.stdout,
        stderr=proc.stderr,
        returncode=proc.returncode,
    )
