"""Validate commit attestation."""

import json
import os
import subprocess
from pathlib import Path

import click

from ..display.output import console, success, error, info


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,
    )
    import hashlib
    return hashlib.sha256(result.stdout.encode()).hexdigest()


def _parse_attestation(path: Path) -> dict[str, str]:
    """Parse key-value pairs from attestation file."""
    content = path.read_text()
    result = {}
    for line in content.splitlines():
        line = line.strip()
        if ":" in line and not line.startswith("#") and not line.startswith("---"):
            key, _, value = line.partition(":")
            key = key.strip().replace(" ", "_")
            value = value.strip().strip("\"'")
            if key and value:
                result[key] = value
    return result


@click.command()
def check() -> None:
    """Validate commit attestation.

    Checks that .commit-attestation.md exists and its staged_diff_hash
    matches the current staged changes. Used by the pre-commit hook,
    also usable standalone.

    \b
    Exit codes:
        0 - Attestation valid (or no .gjalla config)
        1 - Attestation missing or stale
    """
    repo_root = _get_repo_root()

    # No .gjalla config = not a guardrails project, pass through
    gjalla_config = repo_root / ".gjalla" / "config.json"
    if not gjalla_config.exists():
        # Also check old format (.gjalla as a file)
        old_config = repo_root / ".gjalla"
        if not old_config.is_file():
            return
        gjalla_config = old_config

    # Skip if env var set
    if os.environ.get("SKIP_ATTESTATION") == "1":
        info("Attestation skipped (SKIP_ATTESTATION=1)")
        return

    attestation_path = repo_root / ".commit-attestation.md"
    if not attestation_path.exists():
        try:
            config = json.loads(gjalla_config.read_text())
            project_id = config.get("project_id", "unknown")
            api_url = config.get("api_url", "https://gjalla.io")
        except (json.JSONDecodeError, OSError):
            project_id = "unknown"
            api_url = "https://gjalla.io"

        diff_hash = _get_staged_diff_hash()
        console.print()
        console.print("[bold red]gjalla: Attestation Required[/bold red]")
        console.print()
        console.print("  Create .commit-attestation.md before committing.")
        console.print("  See format: .gjalla/example-attestation.md")
        console.print()
        console.print(f"  staged_diff_hash: {diff_hash}")
        console.print()
        console.print("  Fetch latest rules from gjalla to ensure")
        console.print("  your context is fresh before attesting.")
        console.print()
        console.print(f"  Human? Skip: SKIP_ATTESTATION=1 git commit ...")
        console.print()
        raise SystemExit(1)

    # Validate diff hash
    fields = _parse_attestation(attestation_path)
    attested_hash = fields.get("staged_diff_hash", "")
    current_hash = _get_staged_diff_hash()

    if attested_hash != current_hash:
        error("Attestation stale — staged changes differ from attested hash")
        console.print(f"  Expected: {attested_hash[:16]}...")
        console.print(f"  Current:  {current_hash[:16]}...")
        raise SystemExit(1)

    success("Attestation verified")
