"""Command-line interface for AyAiAy."""

from __future__ import annotations

import sys
from pathlib import Path
from typing import Any

import click
import httpx
from rich.console import Console
from rich.panel import Panel
from rich.table import Table
from rich.text import Text

from ayaiay import __version__
from ayaiay.client import AyAiAyClient, AyAiAyError
from ayaiay.config import Config
from ayaiay.installer import Installer, PackReference
from ayaiay.models import PackVersion
from ayaiay.package_manager import PackageManager
from ayaiay.validator import validate_manifest

console = Console()
error_console = Console(stderr=True)


def print_error(message: str) -> None:
    """Print an error message."""
    error_console.print(f"[red]Error:[/red] {message}")


def print_success(message: str) -> None:
    """Print a success message."""
    console.print(f"[green]✓[/green] {message}")


def print_warning(message: str) -> None:
    """Print a warning message."""
    console.print(f"[yellow]Warning:[/yellow] {message}")


def handle_api_connection_error(config: Config, exception: httpx.RequestError) -> None:
    """Handle API connection errors with informative message and exit.

    Args:
        config: Configuration object containing API URL.
        exception: The httpx.RequestError that was raised.
    """
    error_msg = (
        "Unable to connect to the API. This could be due to:\n"
        "  • No internet connection\n"
        "  • API service is not available or unreachable\n"
        f"  • Invalid API URL: {config.api_base_url}\n\n"
        "Try:\n"
        "  • Check your internet connection\n"
        "  • Verify the API URL with 'ayaiay info'\n"
        "  • Set a custom API URL with --api-url or AYAIAY_API_URL\n"
        f"  • See documentation at: https://github.com/ayaiayorg/ayaiay-cli#readme"
    )
    print_error(error_msg)
    sys.exit(1)


@click.group()
@click.version_option(version=__version__, prog_name="ayaiay")
@click.option(
    "--api-url",
    envvar="AYAIAY_API_URL",
    help="API base URL (default: https://api.ayaiay.org)",
)
@click.pass_context
def main(ctx: click.Context, api_url: str | None) -> None:
    """AyAiAy CLI - Marketplace for AI Agent Profiles, Instructions, and Prompts.

    Discover, install, and manage AI packs from the AyAiAy marketplace.
    """
    ctx.ensure_object(dict)
    config = Config.load()
    if api_url:
        config.api_base_url = api_url
    ctx.obj["config"] = config


@main.command()
@click.argument("query", required=False)
@click.option(
    "--type", "-t", "pack_type", type=click.Choice(["agent", "instruction", "prompt"])
)
@click.option("--tag", "-g", "tags", multiple=True, help="Filter by tag")
@click.option("--limit", "-l", default=20, help="Number of results")
@click.option("--page", "-p", default=1, help="Page number")
@click.pass_context
def search(
    ctx: click.Context,
    query: str | None,
    pack_type: str | None,
    tags: tuple[str, ...],
    limit: int,
    page: int,
) -> None:
    """Search for packs in the marketplace.

    Examples:
        ayaiay search "code review"
        ayaiay search --type agent
        ayaiay search --tag python --tag testing
    """
    config: Config = ctx.obj["config"]

    with AyAiAyClient(config=config) as client:
        try:
            result = client.search_packs(
                query=query,
                pack_type=pack_type,
                tags=list(tags) if tags else None,
                page=page,
                per_page=limit,
            )
        except httpx.RequestError as e:
            handle_api_connection_error(config, e)
        except AyAiAyError as e:
            print_error(str(e))
            sys.exit(1)

    if not result.packs:
        console.print("[dim]No packs found.[/dim]")
        return

    table = Table(title=f"Search Results ({result.total} total)")
    table.add_column("Pack", style="cyan", no_wrap=True)
    table.add_column("Type", style="magenta")
    table.add_column("Version", style="green")
    table.add_column("Description")
    table.add_column("Downloads", justify="right")

    for pack in result.packs:
        table.add_row(
            pack.full_name,
            pack.pack_type.value if pack.pack_type else "-",
            pack.latest_version or "-",
            (
                (pack.description or "")[:50] + "..."
                if pack.description and len(pack.description) > 50
                else pack.description or "-"
            ),
            str(pack.downloads),
        )

    console.print(table)

    if result.has_more:
        console.print(
            f"\n[dim]Showing page {result.page}. "
            f"Use --page {result.page + 1} for more.[/dim]"
        )


@main.command()
@click.argument("reference")
@click.option(
    "--force", "-f", is_flag=True, help="Force reinstall if already installed"
)
@click.pass_context
def install(ctx: click.Context, reference: str, force: bool) -> None:
    """Install a pack from the marketplace.

    REFERENCE format: publisher/pack-name[@version]

    Examples:
        ayaiay install acme/code-reviewer
        ayaiay install acme/code-reviewer@1.0.0
        ayaiay install acme/code-reviewer@latest
    """
    config: Config = ctx.obj["config"]
    installer = Installer(config=config)

    console.print(f"[dim]Installing {reference}...[/dim]")

    result = installer.install(reference, force=force)

    if result.success:
        print_success(result.message)
        if result.install_path:
            console.print(f"[dim]Location: {result.install_path}[/dim]")
        pm = PackageManager(config=config)
        if pm.lock_file_path.exists() and isinstance(result.version, PackVersion):
            updated, message = pm.record_installation(reference, result)
            if updated:
                console.print(f"[dim]{message}[/dim]")
            else:
                print_warning(message)
    else:
        print_error(result.message)
        sys.exit(1)


@main.command()
@click.argument("reference")
@click.pass_context
def uninstall(ctx: click.Context, reference: str) -> None:
    """Uninstall a pack.

    REFERENCE format: publisher/pack-name

    Examples:
        ayaiay uninstall acme/code-reviewer
    """
    config: Config = ctx.obj["config"]
    installer = Installer(config=config)

    result = installer.uninstall(reference)

    if result.success:
        print_success(result.message)
        pm = PackageManager(config=config)
        if pm.lock_file_path.exists():
            updated, message = pm.record_uninstall(reference)
            if updated:
                console.print(f"[dim]{message}[/dim]")
            else:
                print_warning(message)
    else:
        print_error(result.message)
        sys.exit(1)


@main.command("list")
@click.pass_context
def list_packs(ctx: click.Context) -> None:
    """List installed packs."""
    config: Config = ctx.obj["config"]
    installer = Installer(config=config)

    installed = installer.list_installed()

    if not installed:
        console.print("[dim]No packs installed.[/dim]")
        return

    table = Table(title="Installed Packs")
    table.add_column("Pack", style="cyan", no_wrap=True)
    table.add_column("Version", style="green")
    table.add_column("Location", style="dim")

    for full_name, version, path in installed:
        table.add_row(full_name, version, str(path))

    console.print(table)


@main.command()
@click.argument("path", type=click.Path(exists=True, path_type=Path))
@click.option("--quiet", "-q", is_flag=True, help="Only output errors")
def validate(path: Path, quiet: bool) -> None:
    """Validate an ayaiay.yaml manifest file.

    Examples:
        ayaiay validate ayaiay.yaml
        ayaiay validate ./my-pack/ayaiay.yaml
    """
    result = validate_manifest(path)

    if result.is_valid:
        if not quiet:
            print_success(f"Manifest is valid: {path}")

            if result.manifest:
                info = Text()
                info.append("Name: ", style="dim")
                info.append(f"{result.manifest.name}\n", style="cyan")

                if result.manifest.description:
                    info.append("Description: ", style="dim")
                    info.append(f"{result.manifest.description}\n")

                counts = []
                if result.manifest.agents:
                    counts.append(f"{len(result.manifest.agents)} agents")
                if result.manifest.instructions:
                    counts.append(f"{len(result.manifest.instructions)} instructions")
                if result.manifest.prompts:
                    counts.append(f"{len(result.manifest.prompts)} prompts")
                if result.manifest.skills:
                    counts.append(f"{len(result.manifest.skills)} skills")

                if counts:
                    info.append("Contents: ", style="dim")
                    info.append(", ".join(counts))

                console.print(Panel(info, title="Manifest Info", border_style="green"))

        for warning in result.warnings:
            print_warning(warning)
    else:
        print_error(f"Manifest validation failed: {path}")
        for error in result.errors:
            console.print(f"  [red]•[/red] {error}")
        sys.exit(1)


@main.command()
@click.pass_context
def info(ctx: click.Context) -> None:
    """Show CLI configuration and status."""
    config: Config = ctx.obj["config"]

    table = Table(title="AyAiAy CLI Configuration")
    table.add_column("Setting", style="cyan")
    table.add_column("Value")

    table.add_row("API URL", config.api_base_url)
    table.add_row("Registry URL", config.registry_url)
    table.add_row("Install Directory", str(config.install_dir))
    table.add_row("Cache Directory", str(config.cache_dir))
    table.add_row("Timeout", f"{config.timeout}s")
    table.add_row("Authenticated", "Yes" if config.token else "No")

    console.print(table)

    # Check API health
    with AyAiAyClient(config=config) as client:
        healthy = client.health_check()
        status = "[green]Connected[/green]" if healthy else "[red]Unreachable[/red]"
        console.print(f"\nAPI Status: {status}")


@main.command()
@click.argument("reference")
@click.pass_context
def show(ctx: click.Context, reference: str) -> None:
    """Show details for a specific pack.

    REFERENCE format: publisher/pack-name

    Examples:
        ayaiay show acme/code-reviewer
    """
    config: Config = ctx.obj["config"]

    try:
        pack_ref = PackReference.parse(reference)
    except ValueError as e:
        print_error(str(e))
        sys.exit(1)

    with AyAiAyClient(config=config) as client:
        try:
            pack = client.get_pack(pack_ref.full_name)
            versions = client.get_pack_versions(pack_ref.full_name)
        except httpx.RequestError as e:
            handle_api_connection_error(config, e)
        except AyAiAyError as e:
            print_error(str(e))
            sys.exit(1)

    # Pack info panel
    info = Text()
    info.append("Name: ", style="dim")
    info.append(f"{pack.full_name}\n", style="cyan bold")
    info.append("Type: ", style="dim")
    info.append(
        f"{pack.pack_type.value if pack.pack_type else 'N/A'}\n",
        style="magenta",
    )

    if pack.description:
        info.append("Description: ", style="dim")
        info.append(f"{pack.description}\n")

    info.append("Latest Version: ", style="dim")
    info.append(f"{pack.latest_version or 'N/A'}\n", style="green")

    info.append("Downloads: ", style="dim")
    info.append(f"{pack.downloads}\n")

    if pack.tags:
        info.append("Tags: ", style="dim")
        info.append(", ".join(pack.tags) + "\n")

    if pack.repository_url:
        info.append("Repository: ", style="dim")
        info.append(f"{pack.repository_url}\n", style="blue underline")

    console.print(Panel(info, title="Pack Details", border_style="cyan"))

    # Versions table
    if versions:
        version_table = Table(title="Available Versions")
        version_table.add_column("Version", style="green")
        version_table.add_column("Published", style="dim")
        version_table.add_column("Downloads", justify="right")

        for v in versions[:10]:  # Show latest 10
            published = v.published_at.strftime("%Y-%m-%d") if v.published_at else "-"
            version_table.add_row(v.version, published, str(v.downloads))

        console.print(version_table)

        if len(versions) > 10:
            console.print(f"[dim]... and {len(versions) - 10} more versions[/dim]")


@main.command("init-pack")
@click.option(
    "--path",
    "-p",
    type=click.Path(path_type=Path),
    help="Path where to create the pack (default: current directory)",
)
def init_pack(path: Path | None) -> None:
    """Initialize a new pack with interactive prompts.

    Creates a new ayaiay.yaml manifest file with selected artifacts
    (agents, instructions, prompts, skills).

    Example:
        ayaiay init-pack
        ayaiay init-pack --path /path/to/new-pack
    """
    import yaml

    target_path = path or Path.cwd()
    manifest_path = target_path / "ayaiay.yaml"

    if manifest_path.exists():
        print_error(f"Manifest already exists: {manifest_path}")
        console.print("[dim]Use a different path or remove the existing file.[/dim]")
        sys.exit(1)

    console.print(
        Panel(
            "[bold cyan]Pack Initialization Wizard[/bold cyan]\n\n"
            "This wizard will help you create a new pack manifest.",
            border_style="cyan",
        )
    )

    # Basic pack information
    console.print("\n[bold]Basic Information[/bold]")

    pack_name = click.prompt("Pack name (e.g., my-awesome-pack)", type=str)
    description = click.prompt(
        "Description", type=str, default="", show_default=False
    )
    author = click.prompt("Author", type=str, default="", show_default=False)
    license_type = click.prompt("License", type=str, default="MIT")
    repository = click.prompt(
        "Repository URL", type=str, default="", show_default=False
    )

    tags_input = click.prompt(
        "Tags (comma-separated)", type=str, default="", show_default=False
    )
    tags = [tag.strip() for tag in tags_input.split(",") if tag.strip()]

    # Artifact collection
    manifest_data: dict[str, Any] = {
        "version": "1.0",
        "name": pack_name,
    }

    if description:
        manifest_data["description"] = description
    if author:
        manifest_data["author"] = author
    if license_type:
        manifest_data["license"] = license_type
    if repository:
        manifest_data["repository"] = repository
    if tags:
        manifest_data["tags"] = tags

    # Ask about each artifact type
    console.print("\n[bold]Artifacts[/bold]")
    console.print("[dim]Select which artifacts you want to add to your pack.[/dim]")

    # Agents
    if click.confirm("\nAdd agents?", default=False):
        agents = []
        while True:
            console.print("\n[cyan]Agent Configuration[/cyan]")
            agent_name = click.prompt("  Agent name", type=str)
            agent_desc = click.prompt(
                "  Description", type=str, default="", show_default=False
            )
            system_prompt = click.prompt(
                "  System prompt", type=str, default="", show_default=False
            )
            model = click.prompt(
                "  Preferred model (e.g., gpt-4, claude-3)",
                type=str,
                default="",
                show_default=False,
            )
            tools_input = click.prompt(
                "  Required tools (comma-separated)",
                type=str,
                default="",
                show_default=False,
            )
            tools = [t.strip() for t in tools_input.split(",") if t.strip()]

            agent: dict[str, Any] = {"name": agent_name}
            if agent_desc:
                agent["description"] = agent_desc
            if system_prompt:
                agent["system_prompt"] = system_prompt
            if model:
                agent["model"] = model
            if tools:
                agent["tools"] = tools

            agents.append(agent)

            if not click.confirm("Add another agent?", default=False):
                break

        manifest_data["agents"] = agents

    # Instructions
    if click.confirm("\nAdd instructions?", default=False):
        instructions = []
        while True:
            console.print("\n[cyan]Instruction Configuration[/cyan]")
            instruction_name = click.prompt("  Instruction name", type=str)
            instruction_desc = click.prompt(
                "  Description", type=str, default="", show_default=False
            )
            content = click.prompt("  Content", type=str)

            instruction: dict[str, Any] = {"name": instruction_name, "content": content}
            if instruction_desc:
                instruction["description"] = instruction_desc

            instructions.append(instruction)

            if not click.confirm("Add another instruction?", default=False):
                break

        manifest_data["instructions"] = instructions

    # Prompts
    if click.confirm("\nAdd prompts?", default=False):
        prompts = []
        while True:
            console.print("\n[cyan]Prompt Configuration[/cyan]")
            prompt_name = click.prompt("  Prompt name", type=str)
            prompt_desc = click.prompt(
                "  Description", type=str, default="", show_default=False
            )
            template = click.prompt("  Template", type=str)
            variables_input = click.prompt(
                "  Variables (comma-separated)",
                type=str,
                default="",
                show_default=False,
            )
            variables = [v.strip() for v in variables_input.split(",") if v.strip()]

            prompt: dict[str, Any] = {"name": prompt_name, "template": template}
            if prompt_desc:
                prompt["description"] = prompt_desc
            if variables:
                prompt["variables"] = variables

            prompts.append(prompt)

            if not click.confirm("Add another prompt?", default=False):
                break

        manifest_data["prompts"] = prompts

    # Skills
    if click.confirm("\nAdd skills?", default=False):
        skills = []
        while True:
            console.print("\n[cyan]Skill Configuration[/cyan]")
            skill_name = click.prompt("  Skill name", type=str)
            skill_desc = click.prompt(
                "  Description", type=str, default="", show_default=False
            )
            skill_content = click.prompt("  Content/Implementation", type=str)
            parameters_input = click.prompt(
                "  Parameters (comma-separated)",
                type=str,
                default="",
                show_default=False,
            )
            parameters = [p.strip() for p in parameters_input.split(",") if p.strip()]

            skill: dict[str, Any] = {"name": skill_name, "content": skill_content}
            if skill_desc:
                skill["description"] = skill_desc
            if parameters:
                skill["parameters"] = parameters

            skills.append(skill)

            if not click.confirm("Add another skill?", default=False):
                break

        manifest_data["skills"] = skills

    # Write manifest file
    target_path.mkdir(parents=True, exist_ok=True)

    with open(manifest_path, "w") as f:
        yaml.dump(manifest_data, f, default_flow_style=False, sort_keys=False)

    print_success(f"Created pack manifest: {manifest_path}")

    # Validate the created manifest
    result = validate_manifest(manifest_path)

    if result.is_valid:
        console.print("[green]✓[/green] Manifest is valid!")

        # Show summary
        counts = []
        if manifest_data.get("agents"):
            counts.append(f"{len(manifest_data['agents'])} agent(s)")
        if manifest_data.get("instructions"):
            counts.append(f"{len(manifest_data['instructions'])} instruction(s)")
        if manifest_data.get("prompts"):
            counts.append(f"{len(manifest_data['prompts'])} prompt(s)")
        if manifest_data.get("skills"):
            counts.append(f"{len(manifest_data['skills'])} skill(s)")

        if counts:
            console.print(f"[dim]Added: {', '.join(counts)}[/dim]")

        for warning in result.warnings:
            print_warning(warning)
    else:
        print_error("Created manifest has validation errors:")
        for error in result.errors:
            console.print(f"  [red]•[/red] {error}")
        sys.exit(1)


@main.command("init-skill")
@click.option(
    "--name",
    "-n",
    type=str,
    help="Skill name (interactive if not provided)",
)
@click.option(
    "--path",
    "-p",
    type=click.Path(path_type=Path),
    help="Path where to create the skill file (default: current directory)",
)
@click.option(
    "--output",
    "-o",
    type=str,
    help="Output filename (default: <skill-name>.md)",
)
def init_skill(name: str | None, path: Path | None, output: str | None) -> None:
    """Generate a GitHub Copilot agent skill skeleton.

    Creates a new skill file following GitHub Copilot's agent skill format.
    Skills define specific capabilities or actions that agents can perform.

    See: https://docs.github.com/en/copilot/concepts/agents/about-agent-skills

    Example:
        ayaiay init-skill
        ayaiay init-skill --name code-analyzer
        ayaiay init-skill --name file-reader --path ./skills
    """
    target_path = path or Path.cwd()
    target_path.mkdir(parents=True, exist_ok=True)

    console.print(
        Panel(
            "[bold cyan]GitHub Copilot Agent Skill Generator[/bold cyan]\n\n"
            "This wizard will help you create a new agent skill.\n"
            "Skills define specific capabilities or actions that agents can perform.",
            border_style="cyan",
        )
    )

    # Get skill details
    console.print("\n[bold]Skill Configuration[/bold]")

    if not name:
        name = click.prompt("Skill name (e.g., code-analyzer, file-reader)", type=str)

    description = click.prompt(
        "Description",
        type=str,
        default="",
        show_default=False,
    )

    # Ask for function signature
    console.print("\n[bold]Function Signature[/bold]")
    console.print("[dim]Define the skill's input parameters.[/dim]")

    parameters = []
    if click.confirm("\nAdd input parameters?", default=True):
        while True:
            param_name = click.prompt("  Parameter name", type=str)
            param_type = click.prompt(
                "  Parameter type (e.g., string, number, boolean, array)",
                type=str,
                default="string",
            )
            param_desc = click.prompt(
                "  Parameter description",
                type=str,
                default="",
                show_default=False,
            )
            param_required = click.confirm("  Required?", default=True)

            parameters.append({
                "name": param_name,
                "type": param_type,
                "description": param_desc,
                "required": param_required,
            })

            if not click.confirm("\n  Add another parameter?", default=False):
                break

    # Ask for return type
    return_type = click.prompt(
        "\nReturn type (e.g., string, object, array)",
        type=str,
        default="string",
    )

    # Generate skill content
    skill_content = _generate_skill_content(
        name=name,
        description=description,
        parameters=parameters,
        return_type=return_type,
    )

    # Determine output filename
    if not output:
        # Convert skill name to kebab-case for filename
        output = name.lower().replace(" ", "-").replace("_", "-") + ".md"
    elif not output.endswith(".md"):
        output = output + ".md"

    skill_file_path = target_path / output

    if skill_file_path.exists() and not click.confirm(
        f"\n[yellow]File already exists: {skill_file_path}[/yellow]\nOverwrite?",
        default=False,
    ):
        console.print("[dim]Aborted.[/dim]")
        sys.exit(0)

    # Write skill file
    with open(skill_file_path, "w") as f:
        f.write(skill_content)

    print_success(f"Created skill file: {skill_file_path}")
    console.print(
        "\n[dim]Next steps:[/dim]\n"
        "  1. Review and customize the generated skill\n"
        "  2. Implement the skill logic in the 'Implementation' section\n"
        "  3. Add the skill to your ayaiay.yaml manifest or use it directly\n"
        "  4. Test the skill with your agent\n"
    )


def _generate_skill_content(
    name: str,
    description: str,
    parameters: list[dict[str, Any]],
    return_type: str,
) -> str:
    """Generate skill file content following GitHub Copilot's format.

    Args:
        name: Skill name
        description: Skill description
        parameters: List of parameter definitions
        return_type: Return type of the skill

    Returns:
        Formatted skill content as markdown
    """
    # Generate parameter list for function signature
    param_signature = (
        ", ".join([p["name"] for p in parameters]) if parameters else ""
    )

    # Generate parameter documentation
    params_doc = ""
    if parameters:
        params_doc = "\n## Parameters\n\n"
        for param in parameters:
            is_required = param.get("required", True)
            required_marker = " (required)" if is_required else " (optional)"
            params_doc += (
                f"- **{param['name']}** (`{param['type']}`){required_marker}"
            )
            if param.get("description"):
                params_doc += f": {param['description']}"
            params_doc += "\n"

    # Generate the skill content
    skill_name_display = name.lower().replace("-", " ").replace("_", " ")
    default_desc = f"A custom skill that performs {name} operations."
    content = f"""# {name}

{description if description else default_desc}

## Overview

This skill provides functionality for {skill_name_display}.

## Function Signature

```typescript
function {name.replace('-', '_').replace(' ', '_')}({param_signature}): {return_type}
```
{params_doc}
## Returns

- **Type**: `{return_type}`
- **Description**: The result of the {skill_name_display} operation.

## Implementation

<!-- Add your skill implementation here -->

### Prerequisites

List any prerequisites or setup requirements:

- Required tools or dependencies
- Environment configuration
- Access permissions

### Steps

1. **Step 1**: Describe the first step
2. **Step 2**: Describe the second step
3. **Step 3**: Continue with additional steps as needed

### Example Usage

```typescript
// Example 1: Basic usage"""

    # Generate example call with parameters
    if parameters:
        example_params = []
        for p in parameters:
            if p["type"] == "string":
                example_params.append(f'"{p["name"]}"')
            else:
                example_params.append(p["name"])
        func_name = name.replace("-", "_").replace(" ", "_")
        params_str = ", ".join(example_params)
        example_call = f"{func_name}({params_str})"
    else:
        example_call = f"{name.replace('-', '_').replace(' ', '_')}()"

    content += f"""
const result = {example_call};
console.log(result);

// Example 2: Advanced usage
// Add more examples as needed
```

### Error Handling

Describe how the skill handles errors:

- **Invalid input**: What happens when parameters are invalid
- **Missing permissions**: How permission errors are handled
- **Network issues**: How connectivity problems are managed
- **Other errors**: Any other error scenarios

### Best Practices

- Use appropriate error handling
- Validate all inputs
- Follow security best practices
- Document any assumptions
- Add logging for debugging

## Testing

### Test Cases

1. **Test Case 1**: Basic functionality
   - Input: Describe input
   - Expected Output: Describe expected result

2. **Test Case 2**: Edge cases
   - Input: Describe edge case input
   - Expected Output: Describe expected result

3. **Test Case 3**: Error scenarios
   - Input: Describe error-triggering input
   - Expected Output: Describe error handling

## Notes

Add any additional notes, limitations, or considerations:

- Performance considerations
- Known limitations
- Future improvements
- Related skills or dependencies

## References

- [GitHub Copilot Agent Skills Documentation](https://docs.github.com/en/copilot/concepts/agents/about-agent-skills)
- Add other relevant documentation links
"""

    return content


@main.command()
@click.option(
    "--path",
    "-p",
    type=click.Path(path_type=Path),
    help="Path to ayaiay.json (default: current directory)",
)
@click.pass_context
def init(ctx: click.Context, path: Path | None) -> None:
    """Initialize a new ayaiay.json file for package management.

    This creates a lock file that tracks all installed packs with their versions,
    similar to composer.json in PHP or package.json in Node.js.

    Example:
        ayaiay init
        ayaiay init --path /path/to/project
    """
    lock_file_path = (path / "ayaiay.json") if path else None
    pm = PackageManager(lock_file_path=lock_file_path)

    if pm.init():
        print_success(f"Created {pm.lock_file_path}")
        console.print(
            "[dim]Use 'ayaiay add <package>' to add packages to your project.[/dim]"
        )
    else:
        print_error(f"Lock file already exists: {pm.lock_file_path}")
        sys.exit(1)


@main.command()
@click.argument("reference")
@click.option(
    "--force", "-f", is_flag=True, help="Force reinstall if already installed"
)
@click.option(
    "--path",
    "-p",
    type=click.Path(path_type=Path),
    help="Path to ayaiay.json directory",
)
@click.pass_context
def add(ctx: click.Context, reference: str, force: bool, path: Path | None) -> None:
    """Add a package to ayaiay.json and install it.

    REFERENCE format: publisher/pack-name[@version]

    The package will be added to ayaiay.json and installed to the local directory.
    This allows you to track all dependencies in one file.

    Examples:
        ayaiay add acme/code-reviewer
        ayaiay add acme/code-reviewer@1.0.0
        ayaiay add acme/code-reviewer --force
    """
    config: Config = ctx.obj["config"]
    lock_file_path = (path / "ayaiay.json") if path else None
    pm = PackageManager(config=config, lock_file_path=lock_file_path)

    console.print(f"[dim]Adding {reference} to {pm.lock_file_path}...[/dim]")

    success, message, result = pm.add_package(reference, force=force)

    if success:
        print_success(message)
        if result.install_path:
            console.print(f"[dim]Location: {result.install_path}[/dim]")
    else:
        print_error(message)
        sys.exit(1)


@main.command()
@click.argument("reference")
@click.option(
    "--path",
    "-p",
    type=click.Path(path_type=Path),
    help="Path to ayaiay.json directory",
)
@click.pass_context
def remove(ctx: click.Context, reference: str, path: Path | None) -> None:
    """Remove a package from ayaiay.json and uninstall it.

    REFERENCE format: publisher/pack-name

    Examples:
        ayaiay remove acme/code-reviewer
    """
    config: Config = ctx.obj["config"]
    lock_file_path = (path / "ayaiay.json") if path else None
    pm = PackageManager(config=config, lock_file_path=lock_file_path)

    success, message = pm.remove_package(reference)

    if success:
        print_success(message)
    else:
        print_error(message)
        sys.exit(1)


@main.command()
@click.option(
    "--path",
    "-p",
    type=click.Path(path_type=Path),
    help="Path to ayaiay.json directory",
)
@click.pass_context
def sync(ctx: click.Context, path: Path | None) -> None:
    """Sync installed packages with ayaiay.json.

    Installs all packages listed in ayaiay.json that aren't currently installed.
    Useful after cloning a project or checking out a different branch.

    Example:
        ayaiay sync
    """
    config: Config = ctx.obj["config"]
    lock_file_path = (path / "ayaiay.json") if path else None
    pm = PackageManager(config=config, lock_file_path=lock_file_path)

    if not pm.lock_file_path.exists():
        print_error(f"No lock file found: {pm.lock_file_path}")
        console.print("[dim]Use 'ayaiay init' to create one.[/dim]")
        sys.exit(1)

    console.print(f"[dim]Syncing packages from {pm.lock_file_path}...[/dim]")
    results = pm.sync()

    if not results:
        console.print("[dim]No packages to sync.[/dim]")
        return

    table = Table(title="Sync Results")
    table.add_column("Package", style="cyan")
    table.add_column("Status", style="bold")
    table.add_column("Message")

    for package_name, success, message in results:
        status = "[green]✓[/green]" if success else "[red]✗[/red]"
        table.add_row(package_name, status, message)

    console.print(table)

    failed = [r for r in results if not r[1]]
    if failed:
        sys.exit(1)


@main.command()
@click.argument("package_name", required=False)
@click.option(
    "--path",
    "-p",
    type=click.Path(path_type=Path),
    help="Path to ayaiay.json directory",
)
@click.pass_context
def update(ctx: click.Context, package_name: str | None, path: Path | None) -> None:
    """Update packages to their latest versions.

    Updates packages listed in ayaiay.json to their latest available versions.
    If no package name is provided, updates all packages.

    Examples:
        ayaiay update                    # Update all packages
        ayaiay update acme/code-reviewer # Update specific package
    """
    config: Config = ctx.obj["config"]
    lock_file_path = (path / "ayaiay.json") if path else None
    pm = PackageManager(config=config, lock_file_path=lock_file_path)

    if not pm.lock_file_path.exists():
        print_error(f"No lock file found: {pm.lock_file_path}")
        console.print("[dim]Use 'ayaiay init' to create one.[/dim]")
        sys.exit(1)

    target = package_name or "all packages"
    console.print(f"[dim]Updating {target}...[/dim]")

    results = pm.update(package_name=package_name)

    if not results:
        console.print("[dim]No packages to update.[/dim]")
        return

    table = Table(title="Update Results")
    table.add_column("Package", style="cyan")
    table.add_column("Status", style="bold")
    table.add_column("Message")

    for pkg_name, success, message in results:
        status = "[green]✓[/green]" if success else "[red]✗[/red]"
        table.add_row(pkg_name, status, message)

    console.print(table)

    failed = [r for r in results if not r[1]]
    if failed:
        sys.exit(1)


if __name__ == "__main__":
    main()
