"""Create a structured commit attestation."""

import json
from datetime import datetime, timezone
from pathlib import Path

import click
import yaml

from ..display.output import console, success, error, info
from ._shared import get_repo_root, get_staged_diff_hash


@click.command()
@click.option("--staged-diff-hash", required=True, help="SHA-256 of staged diff.")
@click.option("--agent", required=True, help="Agent name (e.g. claude-code, cursor, aider).")
@click.option("--provider", required=True, help="Model provider (e.g. anthropic, openai).")
@click.option("--model", required=True, help="Model ID (e.g. claude-opus-4-6).")
@click.option("--summary", required=True, help="One-line impact summary.")
@click.option("--rules", default=None, help="JSON string: {\"checked\": true, \"applicable\": [...]}.")
@click.option("--arch-changes", default=None, help="JSON string with architecture change primitives.")
@click.option("--timestamp", default=None, help="ISO 8601 timestamp. Auto-generated if omitted.")
def attest(
    staged_diff_hash: str,
    agent: str,
    provider: str,
    model: str,
    summary: str,
    rules: str | None,
    arch_changes: str | None,
    timestamp: str | None,
) -> None:
    """Create .gjalla/.commit-attestation.md from structured flags.

    \b
    This is a convenience shortcut. For richer attestations with full
    architecture detail, write .gjalla/.commit-attestation.md directly
    using the format in .gjalla/example-attestation.md.

    \b
    Example:
        gjalla attest \\
          --staged-diff-hash $(git diff --staged | shasum -a 256 | cut -d' ' -f1) \\
          --agent claude-code --provider anthropic --model claude-opus-4-6 \\
          --summary "Added rate limiting to auth endpoints" \\
          --rules '{"checked": true, "applicable": [...]}' \\
          --arch-changes '{"architecture_elements": {"changed": true, ...}}'
    """
    repo_root = get_repo_root()

    # Validate diff hash matches current staged changes
    current_hash = get_staged_diff_hash()
    if staged_diff_hash != current_hash:
        error("Diff hash mismatch — staged changes have changed since hash was computed")
        console.print(f"  Provided: {staged_diff_hash[:16]}...")
        console.print(f"  Current:  {current_hash[:16]}...")
        raise SystemExit(1)

    # Parse JSON options
    rules_data = None
    if rules:
        try:
            rules_data = json.loads(rules)
        except json.JSONDecodeError as e:
            error(f"Invalid --rules JSON: {e}")
            raise SystemExit(1)

    arch_changes_data = None
    if arch_changes:
        try:
            arch_changes_data = json.loads(arch_changes)
        except json.JSONDecodeError as e:
            error(f"Invalid --arch-changes JSON: {e}")
            raise SystemExit(1)

    # Auto-generate timestamp
    if not timestamp:
        timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")

    # Build attestation document
    attestation = {
        "staged_diff_hash": staged_diff_hash,
        "timestamp": timestamp,
        "agent": agent,
        "agent_provider": provider,
        "agent_model": model,
    }

    if rules_data:
        attestation["rules"] = rules_data

    # Merge architecture change primitives as top-level keys
    if arch_changes_data:
        for key in (
            "architecture_elements", "architecture_connections",
            "architecture_decisions", "data_flows", "tech_stack",
            "external_dependencies", "services", "capabilities",
        ):
            if key in arch_changes_data:
                attestation[key] = arch_changes_data[key]

    attestation["summary"] = summary

    # Write as YAML frontmatter into .gjalla/
    gjalla_dir = repo_root / ".gjalla"
    gjalla_dir.mkdir(parents=True, exist_ok=True)
    attestation_path = gjalla_dir / ".commit-attestation.md"
    yaml_body = yaml.dump(attestation, default_flow_style=False, sort_keys=False)
    attestation_path.write_text(f"---\n{yaml_body}---\n")

    success("Created .gjalla/.commit-attestation.md")
    info("  Run 'git commit' — the pre-commit hook will verify the hash.")
