"""macOS Keychain lookup helpers for GitHub Copilot CLI auth."""

from __future__ import annotations

import json
import logging
import os
import subprocess
import sys
from pathlib import Path

from headroom._subprocess import run

logger = logging.getLogger(__name__)


def read_copilot_oauth_token(*, host: str = "github.com") -> str | None:
    """Return a Copilot CLI OAuth token from macOS Keychain, if available."""

    if sys.platform != "darwin":
        return None

    normalized_host = host.strip().lower() or "github.com"
    login = _read_copilot_config_login()
    services = _split_env_list("GITHUB_COPILOT_KEYCHAIN_SERVICE") or [
        "GitHub Copilot",
        "GitHub Copilot CLI",
        "github-copilot",
        "copilot",
        "copilot-cli",
        "GitHub CLI",
        "github.com",
        f"https://{normalized_host}",
        normalized_host,
    ]
    accounts = _split_env_list("GITHUB_COPILOT_KEYCHAIN_ACCOUNT") or [
        value
        for value in (
            f"https://{normalized_host}:{login}" if login else None,
            f"{normalized_host}:{login}" if login else None,
            login,
            os.environ.get("USER"),
            os.environ.get("USERNAME"),
            normalized_host,
            f"https://{normalized_host}",
        )
        if value
    ]

    for command in _candidate_security_commands(normalized_host, services, accounts):
        token = _run_security_lookup(command)
        if token:
            return token

    return None


def _read_copilot_config_login() -> str | None:
    """Return the last logged-in Copilot CLI username from ~/.copilot/config.json."""

    path = Path(os.environ.get("COPILOT_HOME", str(Path.home() / ".copilot"))) / "config.json"
    try:
        lines = [
            line
            for line in path.read_text(encoding="utf-8").splitlines()
            if not line.lstrip().startswith("//")
        ]
        payload = json.loads("\n".join(lines))
    except Exception:
        return None
    if not isinstance(payload, dict):
        return None
    user = payload.get("lastLoggedInUser")
    if not isinstance(user, dict):
        return None
    login = user.get("login")
    return login.strip() if isinstance(login, str) and login.strip() else None


def _split_env_list(name: str) -> list[str]:
    return [part.strip() for part in os.environ.get(name, "").split(",") if part.strip()]


def _candidate_security_commands(
    host: str,
    services: list[str],
    accounts: list[str],
) -> list[list[str]]:
    commands: list[list[str]] = []
    for service in services:
        commands.append(["security", "find-generic-password", "-s", service, "-w"])
        for account in accounts:
            commands.append(
                ["security", "find-generic-password", "-s", service, "-a", account, "-w"]
            )
    for server in (host, f"https://{host}"):
        commands.append(["security", "find-internet-password", "-s", server, "-w"])
        for account in accounts:
            commands.append(
                ["security", "find-internet-password", "-s", server, "-a", account, "-w"]
            )
    return commands


def _run_security_lookup(command: list[str]) -> str | None:
    try:
        result = run(
            command,
            capture_output=True,
            text=True,
            check=False,
            timeout=5,
        )
    except OSError as exc:
        logger.debug("Unable to invoke macOS Keychain lookup for Copilot auth: %s", exc)
        return None
    except subprocess.TimeoutExpired:
        logger.debug("macOS Keychain lookup timed out for Copilot auth")
        return None

    if result.returncode != 0:
        return None
    token = result.stdout.strip()
    return token or None
