"""
Module: init_command
Description: Pack initialization command with scaffolding

Implements:
    - docs/cli/reference.md#huitzo-init
"""

import platform
import re
import shutil
import subprocess
import sys
import tempfile
from pathlib import Path
from typing import Optional

import httpx
import typer
from jinja2 import Environment, PackageLoader
from rich.console import Console

from huitzo_cli.auth import AuthClient
from huitzo_cli.config import ConfigManager

console = Console()


def validate_name(name: str) -> bool:
    """Validate pack name (lowercase with hyphens only)."""
    return bool(re.match(r"^[a-z0-9]([a-z0-9-]*[a-z0-9])?$", name))


def validate_namespace(namespace: str) -> bool:
    """Validate namespace (lowercase with hyphens only)."""
    return bool(re.match(r"^[a-z0-9]([a-z0-9-]*[a-z0-9])?$", namespace))


def name_to_module(name: str) -> str:
    """Convert pack name to Python module name."""
    return name.replace("-", "_")


def check_namespace_available(namespace: str, auth_client: AuthClient) -> tuple[bool, str | None]:
    """Check if namespace is available via backend API.

    Args:
        namespace: Namespace to check
        auth_client: Authenticated client

    Returns:
        Tuple of (available: bool, error_message: str | None)
    """
    token = auth_client.get_token()
    if not token:
        # Not authenticated - skip backend check, will validate during publish
        return True, None

    api_url = auth_client.get_api_url()
    try:
        resp = httpx.get(
            f"{api_url}/api/v1/namespaces/{namespace}/check",
            headers={"Authorization": f"Bearer {token}"},
            timeout=10,
        )
        if resp.status_code == 200:
            body = resp.json()
            data = body.get("data", {})
            return data.get("available", True), data.get("error")
        if 400 <= resp.status_code < 500:
            try:
                body = resp.json()
                data = body.get("data", {})
                error = (
                    data.get("error")
                    or body.get("detail")
                    or f"Namespace unavailable (HTTP {resp.status_code})"
                )
            except Exception:
                error = f"Namespace check failed (HTTP {resp.status_code})"
            return False, error
        # 5xx: server-side problem — warn but allow, backend validates on publish
        console.print(
            f"[yellow]⚠ Namespace check unavailable (HTTP {resp.status_code}). "
            "Will validate during publish.[/yellow]"
        )
    except httpx.HTTPError:
        # Network error — warn but allow, backend validates on publish
        console.print(
            "[yellow]⚠ Could not reach backend for namespace check. "
            "Will validate during publish.[/yellow]"
        )

    return True, None


def init(
    name: Optional[str] = typer.Argument(None, help="Pack name (e.g., my-pack)"),
    namespace: Optional[str] = typer.Option(None, "--namespace", help="Pack namespace"),
    author: Optional[str] = typer.Option(None, "--author", help="Author name"),
    author_email: Optional[str] = typer.Option(None, "--email", help="Author email"),
    description: Optional[str] = typer.Option(None, "--description", help="Pack description"),
) -> None:
    """Initialize a new Intelligence Pack with scaffolding.

    Creates a project structure with:
    - pyproject.toml (package configuration)
    - huitzo.yaml (pack manifest)
    - Example command and tests
    - README and gitignore
    """
    # Get pack name
    if not name:
        name = typer.prompt("Pack name (lowercase, hyphens OK)")

    if not validate_name(name):
        console.print(
            "[red]❌ Invalid pack name. Use lowercase letters, numbers, and hyphens.[/red]"
        )
        raise typer.Exit(1)

    # Get namespace (default to username if authenticated, otherwise pack name)
    config_manager = ConfigManager()
    auth_client = AuthClient(config_manager)

    if not namespace:
        # Explain what a namespace is
        console.print(
            "\n[dim]→ Namespace is your unique identifier on Huitzo "
            "(e.g., @your-namespace/pack-name)[/dim]"
        )
        console.print("[dim]  You can reuse the same namespace for all your packs.[/dim]\n")

        # Try to get authenticated user's tenant slug
        default_namespace = name  # Fallback to pack name
        prompt_text = "Namespace"

        user_info = auth_client.get_current_user()
        if user_info:
            tenant_slug = user_info.get("tenantSlug")
            if tenant_slug:
                default_namespace = tenant_slug
                console.print(f"[green]✓[/green] Using your namespace: [bold]{tenant_slug}[/bold]")
                prompt_text = "Namespace (press Enter to confirm, or type a different one)"

        namespace = typer.prompt(prompt_text, default=default_namespace)

    if not validate_namespace(namespace):
        console.print(
            "[red]❌ Invalid namespace. Use lowercase letters, numbers, and hyphens.[/red]"
        )
        raise typer.Exit(1)

    # Check namespace availability via backend
    available, error = check_namespace_available(namespace, auth_client)
    if not available:
        console.print(f"[red]❌ {error}[/red]")
        raise typer.Exit(1)

    # ONLY check rate limit for NEW namespaces (available ones)
    # If namespace is available, it's a new namespace - check quota
    allowed, quota_error = config_manager.check_namespace_quota()
    if not allowed:
        console.print(f"[red]❌ {quota_error}[/red]")
        raise typer.Exit(1)

    # Get author info
    if not author:
        author = typer.prompt("Author name", default="Developer")

    if not author_email:
        author_email = typer.prompt("Author email", default="dev@example.com")

    # Get description
    if not description:
        description = typer.prompt("Description", default=f"Intelligence Pack: {name}")

    # Create project directory
    project_root = Path.cwd() / name
    if project_root.exists():
        console.print(f"[red]❌ Directory '{name}' already exists[/red]")
        raise typer.Exit(1)

    project_root.mkdir(parents=True, exist_ok=True)
    module_name = name_to_module(name)

    # Set up Jinja2 environment
    env = Environment(loader=PackageLoader("huitzo_cli", "templates/pack"))

    # Template context
    context = {
        "pack_name": name,
        "namespace": namespace,
        "module_name": module_name,
        "author": author,
        "author_email": author_email,
        "description": description,
    }

    # Create directory structure
    src_dir = project_root / "src" / module_name
    src_dir.mkdir(parents=True, exist_ok=True)

    commands_dir = src_dir / "commands"
    commands_dir.mkdir(parents=True, exist_ok=True)

    tests_dir = project_root / "tests"
    tests_dir.mkdir(parents=True, exist_ok=True)

    # Create docs directory structure
    docs_dir = project_root / "docs"
    docs_commands_dir = docs_dir / "commands"
    docs_guides_dir = docs_dir / "guides"
    docs_commands_dir.mkdir(parents=True, exist_ok=True)
    docs_guides_dir.mkdir(parents=True, exist_ok=True)

    # Render templates
    files_to_create = {
        "pyproject.toml.j2": project_root / "pyproject.toml",
        "huitzo.yaml.j2": project_root / "huitzo.yaml",
        "README.md.j2": project_root / "README.md",
        ".gitignore.j2": project_root / ".gitignore",
        "__init__.py.j2": src_dir / "__init__.py",
        "hello.py.j2": commands_dir / "hello.py",
        "test_hello.py.j2": tests_dir / "test_hello.py",
        "conftest.py.j2": tests_dir / "conftest.py",
    }

    for template_name, target_path in files_to_create.items():
        template = env.get_template(template_name)
        content = template.render(**context)
        target_path.write_text(content)

    # Create __init__.py for commands directory with exports
    commands_init = '''"""Commands for this pack."""

from .hello import hello_world

__all__ = ["hello_world"]
'''
    (commands_dir / "__init__.py").write_text(commands_init)

    # Create __init__.py for tests directory
    (tests_dir / "__init__.py").write_text('"""Tests for this pack."""\n')

    # Create initial documentation
    (docs_dir / "README.md").write_text(
        f"---\ntitle: {name}\ntags: [overview]\ncategory: overview\norder: 1\n---\n\n"
        f"# {name}\n\n{description}\n\n## Commands\n\nSee [commands/](commands/) for available commands.\n\n"
        "## Getting Started\n\nSee [guides/getting-started.md](guides/getting-started.md).\n"
    )
    (docs_commands_dir / "README.md").write_text(
        "---\ntitle: Commands\ntags: [commands]\ncategory: commands\norder: 1\n---\n\n"
        "# Commands\n\nAvailable commands in this pack:\n\n"
        "| Command | Description |\n|---------|-------------|\n"
        "| `hello` | A simple hello world command |\n"
    )
    (docs_commands_dir / "hello.md").write_text(
        "---\ntitle: hello\ntags: [command, example]\ncategory: commands\norder: 2\n---\n\n"
        "# hello\n\nA simple hello world command.\n\n## Arguments\n\n"
        "| Argument | Type | Required | Default | Description |\n"
        "|----------|------|----------|---------|-------------|\n"
        '| `name` | string | no | `"World"` | Name to greet |\n\n'
        "## Returns\n\n```json\n"
        '{\n  "message": "string — greeting message"\n}\n```\n\n'
        "## Examples\n\n### Basic usage\n"
        'Input: `{}`\nOutput: `{"message": "Hello, World!"}`\n\n'
        "### With name\n"
        'Input: `{"name": "Alice"}`\nOutput: `{"message": "Hello, Alice!"}`\n'
    )
    (docs_guides_dir / "README.md").write_text(
        "---\ntitle: Guides\ntags: [guides]\ncategory: guides\norder: 1\n---\n\n"
        "# Guides\n\n- [Getting Started](getting-started.md)\n"
    )
    (docs_guides_dir / "getting-started.md").write_text(
        "---\ntitle: Getting Started\ntags: [guide, quickstart]\ncategory: guides\norder: 2\n---\n\n"
        f"# Getting Started with {name}\n\n## Installation\n\n```bash\n"
        f"# Install the pack\npip install {name}\n```\n\n"
        "## Usage\n\nRun the hello command:\n\n```bash\n"
        f'huitzo run @{namespace}/{name}/hello --args \'{{"name": "World"}}\'\n```\n'
    )

    # Create virtual environment
    console.print("\n[bold]Creating virtual environment...[/bold]")
    venv_dir = project_root / "venv"

    # Find Python 3.11+ (SDK requirement)
    python_exe = None
    for python_cmd in ["python3.13", "python3.12", "python3.11"]:
        found = shutil.which(python_cmd)
        if found:
            # Verify it's not a broken/rc version by testing it
            test_result = subprocess.run(
                [found, "--version"], capture_output=True, text=True, check=False
            )
            if test_result.returncode == 0 and "rc" not in test_result.stdout.lower():
                python_exe = found
                break

    if not python_exe:
        python_exe = sys.executable
        console.print(f"[yellow]⚠️  Python 3.11+ recommended, using {sys.executable}[/yellow]")

    try:
        subprocess.run([python_exe, "-m", "venv", str(venv_dir)], check=True)
        console.print(f"[green]✅ Virtual environment created (using {python_exe})[/green]")

        # Determine pip path based on OS
        if platform.system() == "Windows":
            pip_path = venv_dir / "Scripts" / "pip"
        else:
            pip_path = venv_dir / "bin" / "pip"

        # Install huitzo-sdk
        console.print("[bold]Installing huitzo-sdk...[/bold]")

        # Try to find local SDK first (development monorepo layout)
        sdk_path = Path.cwd().parent / "sdk"
        install_cmd = [str(pip_path), "install"]
        if sdk_path.exists() and (sdk_path / "pyproject.toml").exists():
            install_cmd.extend(["-e", str(sdk_path)])
            console.print("[dim]Installing huitzo-sdk from local source[/dim]")
        else:
            install_cmd.append("huitzo-sdk")

        install_result = subprocess.run(install_cmd, capture_output=True, text=True, check=False)

        if install_result.returncode == 0:
            console.print("[green]✅ huitzo-sdk installed[/green]")

            # Install dev dependencies
            console.print("[bold]Installing dev dependencies...[/bold]")
            dev_install = subprocess.run(
                [str(pip_path), "install", "pytest>=9.0", "pytest-asyncio>=1.0", "pytest-cov>=7.0"],
                capture_output=True,
                text=True,
                check=False,
            )
            if dev_install.returncode == 0:
                console.print("[green]✅ Dev dependencies installed[/green]")
        else:
            console.print("[yellow]⚠️  Could not install huitzo-sdk automatically[/yellow]")
            console.print(
                "[yellow]   Run: source venv/bin/activate && pip install huitzo-sdk[/yellow]"
            )

    except Exception as e:
        console.print(f"[yellow]⚠️  Could not create virtual environment: {e}[/yellow]")
        console.print("[yellow]   You can create it manually with: python -m venv venv[/yellow]")

    console.print(f"\n[green]✅ Pack '{name}' initialized successfully![/green]")
    console.print("\n[bold]Next steps:[/bold]")
    console.print(f"  cd {name}")
    console.print("  source venv/bin/activate  # On Windows: venv\\Scripts\\activate")
    console.print("  huitzo pack validate")
    console.print("  huitzo pack test")
    console.print("  huitzo pack dev")

    # Claude Code environment setup (opt-in)
    _prompt_claude_setup(project_root)


_CLAUDE_ENV_REPO = "https://github.com/Huitzo-Inc/pack-claude-env.git"
_CLAUDE_ENV_MANUAL_URL = "https://github.com/Huitzo-Inc/pack-claude-env"


def _prompt_claude_setup(project_root: Path) -> None:
    """Prompt the user to set up a Claude Code environment."""
    console.print()
    if not typer.confirm(
        "Would you like to set up a Claude Code environment? (requires git)",
        default=False,
    ):
        return

    if not shutil.which("git"):
        console.print(
            f"[yellow]⚠ git is not installed. Install manually: {_CLAUDE_ENV_MANUAL_URL}[/yellow]"
        )
        return

    _clone_claude_env(project_root)


def _clone_claude_env(project_root: Path) -> None:
    """Clone the Claude Code environment repo and copy files into the pack."""
    tmp_dir = None
    try:
        tmp_dir = tempfile.mkdtemp(prefix="pack-claude-env-")
        result = subprocess.run(
            ["git", "clone", "--depth", "1", _CLAUDE_ENV_REPO, tmp_dir],
            capture_output=True,
            text=True,
            check=False,
            timeout=30,
        )
        if result.returncode != 0:
            console.print(
                "[yellow]⚠ Could not clone Claude Code environment. "
                f"Install manually: {_CLAUDE_ENV_MANUAL_URL}[/yellow]"
            )
            return

        # Copy claude/ → .claude/
        src_claude = Path(tmp_dir) / "claude"
        dst_claude = project_root / ".claude"
        if src_claude.is_dir():
            shutil.copytree(src_claude, dst_claude)

        # Copy CONSTITUTION.md
        src_constitution = Path(tmp_dir) / "CONSTITUTION.md"
        dst_constitution = project_root / "CONSTITUTION.md"
        if src_constitution.is_file():
            shutil.copy2(src_constitution, dst_constitution)

        # Install your-docs-mcp in the pack's venv for the MCP documentation server
        _install_docs_mcp(project_root)

        console.print("[green]✅ Claude Code environment set up![/green]")
        console.print(
            "[dim]  Available skills: /draft-docs, /add-command, /test-pack, /validate-pack, /lint-and-fix[/dim]"
        )
        console.print("[dim]  Available agents: docs-writer, pack-developer, pack-reviewer[/dim]")
        console.print(
            "[dim]  Documentation server: your-docs-mcp (serves docs/ to Claude Code)[/dim]"
        )

    except subprocess.TimeoutExpired:
        console.print(
            f"[yellow]⚠ Clone timed out. Install manually: {_CLAUDE_ENV_MANUAL_URL}[/yellow]"
        )
    except Exception:
        console.print(
            "[yellow]⚠ Could not set up Claude Code environment. "
            f"Install manually: {_CLAUDE_ENV_MANUAL_URL}[/yellow]"
        )
    finally:
        if tmp_dir:
            shutil.rmtree(tmp_dir, ignore_errors=True)


def _install_docs_mcp(project_root: Path) -> None:
    """Install your-docs-mcp in the pack's virtual environment."""
    if platform.system() == "Windows":
        pip_path = project_root / "venv" / "Scripts" / "pip"
    else:
        pip_path = project_root / "venv" / "bin" / "pip"

    if not pip_path.exists():
        return

    result = subprocess.run(
        [str(pip_path), "install", "your-docs-mcp"],
        capture_output=True,
        text=True,
        check=False,
        timeout=60,
    )
    if result.returncode == 0:
        console.print("[green]✅ Documentation server (your-docs-mcp) installed[/green]")
    else:
        console.print(
            "[yellow]⚠ Could not install your-docs-mcp. "
            "Install manually: pip install your-docs-mcp[/yellow]"
        )
