"""Initialize gjalla in a repository."""

import json
import os
from pathlib import Path

import click
from rich.prompt import Prompt, Confirm

from gjalla_precommit.display.output import console, success, error, warning, info, panel
from gjalla_precommit.tools.git_tools import is_git_repo, get_remote_url

from ._api import (
    verify_api_key,
    list_projects,
    discover_project,
    select_project_interactively,
    _make_api_headers,
)


# Global config paths
GJALLA_DIR = Path.home() / ".gjalla"
CONFIG_PATH = GJALLA_DIR / "config.yaml"

# API timeout in seconds
API_TIMEOUT = 30.0


def load_global_config() -> dict:
    """Load global gjalla config from ~/.gjalla/config.yaml."""
    import yaml

    if not CONFIG_PATH.exists():
        return {
            "api_key": None,
            "api_url": "https://gjalla.io",
            "projects": {},
        }

    with open(CONFIG_PATH) as f:
        return yaml.safe_load(f) or {}


def save_global_config(config: dict) -> None:
    """Save global gjalla config to ~/.gjalla/config.yaml."""
    import yaml

    GJALLA_DIR.mkdir(parents=True, exist_ok=True)
    with open(CONFIG_PATH, "w") as f:
        yaml.dump(config, f, default_flow_style=False)


@click.command()
@click.option(
    "--api-key",
    envvar="GJALLA_API_KEY",
    help="API key for gjalla cloud. Can also be set via GJALLA_API_KEY env var.",
)
@click.option(
    "--project-id",
    type=int,
    help="Project ID. If not provided, will be auto-discovered from git remote.",
)
@click.option(
    "--yes", "-y",
    is_flag=True,
    help="Accept all defaults without prompting.",
)
def init(
    api_key: str | None,
    project_id: int | None,
    yes: bool = False,
) -> None:
    """Initialize gjalla in the current repository.

    This command sets up gjalla for your repository by:

    \b
    1. Checking git repository
    2. Configuring your API key (optional — skip for local-only usage)
    3. Verifying API key
    4. Selecting your project from Gjalla
    5. Creating .gjalla project config
    6. Updating .gitignore
    7. Installing commit attestation guardrails
    8. Installing MCP server for Claude Code

    Run without --api-key for local-only mode. Use 'gjalla connect' later to link a project.
    """
    repo_path = Path.cwd()

    panel("gjalla Initialization", title="gjalla init")
    console.print()

    # Step 1: Verify we're in a git repo
    info("Step 1/8: Checking git repository...")
    if not is_git_repo(repo_path):
        error("Not a git repository. Please run 'gjalla init' from a git repository.")
        raise SystemExit(1)
    success("Git repository detected")
    console.print()

    # Load existing config
    config = load_global_config()
    api_url = os.environ.get("GJALLA_API_URL") or config.get("api_url", "https://gjalla.io")

    # Determine if we have an API key available
    has_api_key = False
    if api_key:
        has_api_key = True
        info("Step 2/8: Using API key from command line or environment")
    elif config.get("api_key"):
        api_key = config["api_key"]
        has_api_key = True
        info("Step 2/8: Using existing API key from config")
    else:
        info("Step 2/8: API key configuration...")
        if yes:
            info("No API key provided — setting up local-only mode")
            info("  Run 'gjalla connect' later to link to a Gjalla project")
        else:
            api_key = Prompt.ask(
                "[bold]Enter your Gjalla API key[/bold] (get one at https://gjalla.io/settings/api, or press Enter to skip)",
                default="",
                password=True,
            )
            if api_key:
                has_api_key = True
            else:
                info("No API key provided — setting up local-only mode")
                info("  Run 'gjalla connect' later to link to a Gjalla project")

    project_info = None

    if has_api_key:
        success("API key configured")
        console.print()

        # Step 3: Verify API key
        info("Step 3/8: Verifying API key...")
        if not verify_api_key(api_key, api_url):
            error("Invalid API key. Please check your key and try again.")
            raise SystemExit(1)
        success("API key verified")
        console.print()

        # Step 4: Discover/select project
        info("Step 4/8: Selecting project...")
        if project_id:
            info(f"Using provided project ID: {project_id}")
            project_info = {"id": project_id, "name": "unknown"}
        else:
            remote_url = get_remote_url(repo_path)
            if remote_url and not remote_url.startswith("Error:"):
                info(f"Found git remote: {remote_url}")
                discovered = discover_project(remote_url, api_key, api_url)

                if discovered:
                    info(f"Discovered project: {discovered['name']}")
                    if Confirm.ask("Is this the correct project?", default=True):
                        project_info = {"id": discovered["id"], "name": discovered["name"]}

            if not project_info:
                info("Select your project from the available options:")
                project_info = select_project_interactively(api_key, api_url)
                if not project_info:
                    raise SystemExit(1)

        success(f"Selected project: {project_info.get('name', project_info['id'])}")
        console.print()

        # Save config with API key
        config["api_key"] = api_key
        config["api_url"] = api_url
        if "projects" not in config:
            config["projects"] = {}
        config["projects"][str(repo_path)] = str(project_info["id"])
        save_global_config(config)
    else:
        info("  Skipping steps 3-4 (API verification and project selection)")
        console.print()

    # Step 5: Create .gjalla project config
    info("Step 5/8: Creating .gjalla project config...")
    gjalla_dir = repo_path / ".gjalla"

    # Migrate: if .gjalla is an old-format file, move it into the directory
    if gjalla_dir.is_file():
        old_content = gjalla_dir.read_text()
        gjalla_dir.unlink()
        gjalla_dir.mkdir(parents=True, exist_ok=True)
        (gjalla_dir / "config.json").write_text(old_content)
        info("Migrated .gjalla file → .gjalla/config.json")
    else:
        gjalla_dir.mkdir(parents=True, exist_ok=True)

    gjalla_config_data = {
        "project_id": project_info["id"] if project_info else None,
        "api_url": api_url,
        "api_key_env": "GJALLA_API_KEY",
    }
    (gjalla_dir / "config.json").write_text(json.dumps(gjalla_config_data, indent=2) + "\n")

    if project_info:
        success(f"Created .gjalla/config.json (project {project_info['id']})")
    else:
        success("Created .gjalla/config.json (local-only, no project linked)")
    console.print()

    # Step 6: Update .gitignore
    info("Step 6/8: Updating .gitignore...")
    gitignore_path = repo_path / ".gitignore"
    gitignore_content = gitignore_path.read_text() if gitignore_path.exists() else ""
    gitignore_lines = gitignore_content.splitlines()
    entries_to_add = [".gjalla/.commit-attestation.md", ".gjallalog", ".gjalla/attestations/"]
    added = []
    for entry in entries_to_add:
        if entry not in gitignore_lines:
            gitignore_lines.append(entry)
            added.append(entry)
    if added:
        gitignore_path.write_text("\n".join(gitignore_lines) + "\n")
        success(f"Added to .gitignore: {', '.join(added)}")
    else:
        success(".gitignore already up to date")
    console.print()

    # Step 7: Offer guardrails setup
    info("Step 7/8: Commit attestation guardrails...")
    info("This will add precommit hooks to your repository so agents must attest that their changes are compliant with your rules and architecture before committing.")
    if yes or Confirm.ask("Enable?", default=True):
        from .setup import _ensure_gitignore
        from ..hooks.scripts import attestation_pre_commit_script, post_commit_upload_script, example_attestation
        from ..hooks.installer import install_hooks
        import stat

        # Write example attestation
        example_path = gjalla_dir / "example-attestation.md"
        example_path.write_text(example_attestation())
        success("Created .gjalla/example-attestation.md")

        scripts_dir = repo_path / "scripts"
        scripts_dir.mkdir(exist_ok=True)

        pre_path = scripts_dir / "gjalla-attestation-check.sh"
        pre_path.write_text(attestation_pre_commit_script())
        pre_path.chmod(pre_path.stat().st_mode | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH)

        post_path = scripts_dir / "gjalla-post-commit-upload.sh"
        post_path.write_text(post_commit_upload_script())
        post_path.chmod(post_path.stat().st_mode | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH)

        result = install_hooks(
            repo_path,
            pre_commit_command="bash scripts/gjalla-attestation-check.sh",
            post_commit_command="bash scripts/gjalla-post-commit-upload.sh",
        )
        success(f"Pre-commit: {result.pre_commit.message}")
        success(f"Post-commit: {result.post_commit.message}")

        # Generate agent guidance files (appends to CLAUDE.md etc.)
        from .setup import _generate_agent_guidance
        project_id_str = str(project_info["id"]) if project_info else "unknown"
        _generate_agent_guidance(repo_path, project_id_str, yes)
    else:
        info("Skipped. Run 'gjalla setup' later to enable guardrails.")
    console.print()

    # Step 8: MCP server for Claude Code
    info("Step 8/8: MCP server for Claude Code...")
    info("This adds a .mcp.json so Claude Code can access your project's architecture, rules, and context.")
    info("For other editors (Cursor, Windsurf, etc.), see https://gjalla.io/docs/mcp")
    if yes or Confirm.ask("Install for Claude Code?", default=True):
        from .mcp import install_gjalla_entry
        pid = project_info["id"] if project_info else None
        installed = install_gjalla_entry(repo_path, project_id=pid, api_url=api_url, api_key=api_key)
        if installed:
            success("Gjalla MCP server configured in .mcp.json")
        else:
            info("Gjalla MCP server already configured in .mcp.json")
    else:
        info("Skipped. Run 'gjalla mcp install' later to add MCP support.")
    console.print()

    # Build completion message
    if has_api_key:
        completion_msg = "[green]Success! Agents will now have to attest that their changes are compliant with your rules and architecture before committing[/green]\n\n"
        completion_msg += "Run 'gjalla sync' to refresh project context.\n"
        completion_msg += "Run 'gjalla setup' to reconfigure guardrails.\n"
        panel(completion_msg, title="gjalla initialized successfully!")
    else:
        completion_msg = "[green]Success! Local guardrails are active — agents must attest before committing.[/green]\n\n"
        completion_msg += "Connect a Gjalla account to navigate architecture changes,\n"
        completion_msg += "control what agents can do, and track compliance across your team.\n\n"
        completion_msg += "  [bold]gjalla connect[/bold] — link your API key and project\n"
        panel(completion_msg, title="gjalla initialized (local-only)")
