"""Shared git helpers used across CLI commands."""

import hashlib
import json
import os
import subprocess
from pathlib import Path

import click
import yaml


def get_repo_root() -> Path:
    """Find git repository root from current directory."""
    cwd = Path.cwd()
    for parent in [cwd, *cwd.parents]:
        if (parent / ".git").exists():
            return parent
    raise click.ClickException("Not in a git repository")


def get_staged_diff_hash() -> str:
    """Get SHA-256 hash of staged changes."""
    result = subprocess.run(
        ["git", "diff", "--staged"],
        capture_output=True,
        text=True,
    )
    return hashlib.sha256(result.stdout.encode()).hexdigest()


def get_git_user_name() -> str:
    """Get git user.name, falling back to 'unknown'."""
    result = subprocess.run(
        ["git", "config", "user.name"],
        capture_output=True,
        text=True,
    )
    return result.stdout.strip() or "unknown"


def _migrate_local_config_json_to_yaml(repo_root: Path) -> None:
    """One-time migration: if config.json exists but config.yaml doesn't, convert."""
    json_path = repo_root / ".gjalla" / "config.json"
    yaml_path = repo_root / ".gjalla" / "config.yaml"

    if json_path.exists() and not yaml_path.exists():
        try:
            config = json.loads(json_path.read_text())
            yaml_path.write_text(yaml.dump(config, default_flow_style=False))
            json_path.unlink()
        except (json.JSONDecodeError, OSError):
            pass


def load_local_config(repo_root: Path) -> dict:
    """Load .gjalla/config.yaml, auto-migrating from config.json if needed.

    Returns:
        Config dict, or empty dict if no config exists.
    """
    _migrate_local_config_json_to_yaml(repo_root)

    yaml_path = repo_root / ".gjalla" / "config.yaml"
    if not yaml_path.exists():
        return {}

    try:
        return yaml.safe_load(yaml_path.read_text()) or {}
    except yaml.YAMLError:
        return {}


def save_local_config(repo_root: Path, config: dict) -> None:
    """Save config to .gjalla/config.yaml."""
    yaml_path = repo_root / ".gjalla" / "config.yaml"
    yaml_path.parent.mkdir(parents=True, exist_ok=True)
    yaml_path.write_text(yaml.dump(config, default_flow_style=False))


def local_config_exists(repo_root: Path) -> bool:
    """Check if .gjalla/config.yaml (or config.json awaiting migration) exists."""
    return (
        (repo_root / ".gjalla" / "config.yaml").exists()
        or (repo_root / ".gjalla" / "config.json").exists()
    )


def resolve_local_api_key(repo_root: Path) -> tuple[str | None, str | None]:
    """Resolve API key and URL from project-local sources.

    Checks project-local config only (not global config or GJALLA_API_KEY env var,
    which are already handled by Settings.load()). Use this to layer local sources
    on top of Settings.

    Priority order:
    1. Direct api_key in .gjalla/config.yaml
    2. api_key_env (env var reference) in .gjalla/config.yaml

    Returns:
        (api_key, api_url) — either or both may be None.
    """
    local_config = load_local_config(repo_root)
    if not local_config:
        return None, None

    api_url = local_config.get("api_url")

    # 1. Direct api_key field
    direct_key = local_config.get("api_key")
    if direct_key:
        return direct_key, api_url

    # 2. api_key_env (env var reference)
    env_var_name = local_config.get("api_key_env", "")
    if env_var_name:
        key = os.environ.get(env_var_name)
        if key:
            return key, api_url

    return None, api_url
