"""Shell completion support for OCLAWMA CLI.

This module provides shell completion installation and management
for bash and zsh shells.
"""

from __future__ import annotations

import os
from pathlib import Path

import click

from oclawma.cli_ui import (
    header,
    key_value,
    print_error,
    print_info,
    print_success,
    print_warning,
    subheader,
)

# Shell completion script templates
BASH_COMPLETION_TEMPLATE = """
# OCLAWMA Bash Completion
# Generated automatically - do not edit manually

_oclawma_completion() {
    local IFS=$'\\n'
    local response

    response=$(env COMP_WORDS="${COMP_WORDS[*]}" COMP_CWORD=$COMP_CWORD _OCLAWMA_COMPLETE=bash_complete $1)

    for completion in $response; do
        IFS=',' read type value <<< "$completion"
        if [[ $type == 'dir' ]]; then
            COMPREPLY+=("$value/")
        elif [[ $type == 'file' ]]; then
            COMPREPLY+=("$value ")
        else
            COMPREPLY+=("$value ")
        fi
    done

    return 0
}

complete -F _oclawma_completion -o nosort oclawma
"""

ZSH_COMPLETION_TEMPLATE = """
#compdef oclawma

# OCLAWMA Zsh Completion
# Generated automatically - do not edit manually

_oclawma_completion() {
    local -a completions
    local -a descriptions
    local -a response

    response=("${(@f)$(env COMP_WORDS="${words[*]}" COMP_CWORD=$((CURRENT-1)) _OCLAWMA_COMPLETE=zsh_complete oclawma)}")

    for key descr in ${(kv)response}; do
        if [[ "$descr" == "$key" ]]; then
            completions+=("$key")
        else
            completions+=("$key:$descr")
        fi
    done

    _describe -t commands 'oclawma commands' completions
}

compdef _oclawma_completion oclawma
"""


def get_completion_path(shell: str) -> Path | None:
    """Get the appropriate completion file path for the shell.

    Args:
        shell: Shell name (bash or zsh)

    Returns:
        Path to completion file, or None if cannot determine
    """
    home = Path.home()

    if shell == "bash":
        # Common bash completion paths
        paths = [
            home / ".bash_completion.d" / "oclawma",
            home / ".bash_completion" / "oclawma",
            home / ".local" / "share" / "bash-completion" / "completions" / "oclawma",
            Path("/etc/bash_completion.d") / "oclawma",
        ]

        # Check which directories exist
        for p in paths:
            if p.parent.exists():
                return p

        # Default to creating .bash_completion.d
        bash_dir = home / ".bash_completion.d"
        bash_dir.mkdir(parents=True, exist_ok=True)
        return bash_dir / "oclawma"

    elif shell == "zsh":
        # Zsh completions
        zsh_dir = home / ".zsh" / "completions"

        # Check if user has custom fpath
        if zsh_dir.exists():
            return zsh_dir / "_oclawma"

        # Check for oh-my-zsh
        omz_dir = home / ".oh-my-zsh"
        if omz_dir.exists():
            omz_completions = omz_dir / "completions"
            omz_completions.mkdir(parents=True, exist_ok=True)
            return omz_completions / "_oclawma"

        # Default to .zsh/completions
        zsh_dir.mkdir(parents=True, exist_ok=True)
        return zsh_dir / "_oclawma"

    return None


def get_shell_config_file(shell: str) -> Path | None:
    """Get the shell configuration file path.

    Args:
        shell: Shell name (bash or zsh)

    Returns:
        Path to config file, or None if cannot determine
    """
    home = Path.home()

    if shell == "bash":
        # Check for common bash config files
        for name in [".bashrc", ".bash_profile", ".profile"]:
            path = home / name
            if path.exists():
                return path
        return home / ".bashrc"

    elif shell == "zsh":
        return home / ".zshrc"

    return None


def install_completion(shell: str, path: Path | None = None) -> tuple[bool, str]:
    """Install shell completion for the specified shell.

    Args:
        shell: Shell name (bash or zsh)
        path: Custom path for completion file (optional)

    Returns:
        Tuple of (success, message)
    """
    if shell not in ("bash", "zsh"):
        return False, f"Unsupported shell: {shell}. Use 'bash' or 'zsh'."

    # Determine completion file path
    if path is None:
        path = get_completion_path(shell)

    if path is None:
        return False, f"Could not determine completion path for {shell}"

    # Generate completion script
    script = BASH_COMPLETION_TEMPLATE if shell == "bash" else ZSH_COMPLETION_TEMPLATE

    try:
        # Ensure parent directory exists
        path.parent.mkdir(parents=True, exist_ok=True)

        # Write completion file
        path.write_text(script)

        # For bash, may need to source it
        if shell == "bash":
            config_file = get_shell_config_file(shell)
            if config_file:
                source_line = f'[ -f "{path}" ] && source "{path}"'

                # Check if already sourced
                content = config_file.read_text() if config_file.exists() else ""
                if source_line not in content:
                    with open(config_file, "a") as f:
                        f.write(f"\n# OCLAWMA completion\n{source_line}\n")

        # For zsh, may need to add to fpath
        if shell == "zsh":
            config_file = get_shell_config_file(shell)
            if config_file and config_file.exists():
                content = config_file.read_text()
                fpath_line = f'fpath+=("{path.parent}")'
                if fpath_line not in content and str(path.parent) not in content:
                    with open(config_file, "a") as f:
                        f.write(f"\n# OCLAWMA completion\n{fpath_line}\n")

        return True, str(path)

    except Exception as e:
        return False, str(e)


def uninstall_completion(shell: str) -> tuple[bool, str]:
    """Uninstall shell completion for the specified shell.

    Args:
        shell: Shell name (bash or zsh)

    Returns:
        Tuple of (success, message)
    """
    path = get_completion_path(shell)

    if path is None or not path.exists():
        return False, f"No completion file found for {shell}"

    try:
        path.unlink()

        # Clean up source line from config
        config_file = get_shell_config_file(shell)
        if config_file and config_file.exists():
            content = config_file.read_text()
            lines = content.split("\n")
            new_lines = []
            skip_next = False

            for line in lines:
                if "# OCLAWMA completion" in line:
                    skip_next = True
                    continue
                if skip_next:
                    skip_next = False
                    continue
                new_lines.append(line)

            config_file.write_text("\n".join(new_lines))

        return True, str(path)
    except Exception as e:
        return False, str(e)


def show_completion(shell: str) -> str:
    """Show the completion script for the specified shell.

    Args:
        shell: Shell name (bash or zsh)

    Returns:
        Completion script content
    """
    if shell == "bash":
        return BASH_COMPLETION_TEMPLATE
    elif shell == "zsh":
        return ZSH_COMPLETION_TEMPLATE
    else:
        return f"# Unsupported shell: {shell}\n# Supported shells: bash, zsh"


@click.group(name="completion")
def completion_cli() -> None:
    """Manage shell completion for OCLAWMA."""
    pass


@completion_cli.command(name="install")
@click.option(
    "--shell",
    type=click.Choice(["bash", "zsh", "auto"], case_sensitive=False),
    default="auto",
    help="Shell to install completion for (default: auto-detect)",
)
@click.option(
    "--path",
    type=click.Path(),
    help="Custom path for completion file",
)
def install_completion_cmd(shell: str, path: str | None) -> None:
    """Install shell completion.

    Automatically detects your shell if --shell is not specified.

    Examples:
        oclawma completion install
        oclawma completion install --shell bash
        oclawma completion install --shell zsh
    """
    # Auto-detect shell
    if shell == "auto":
        shell = os.environ.get("SHELL", "").split("/")[-1]
        if shell not in ("bash", "zsh"):
            print_error("Could not auto-detect shell. Please specify with --shell")
            return
        print_info(f"Detected shell: {shell}")

    path_obj = Path(path) if path else None

    success_result, message = install_completion(shell, path_obj)

    if success_result:
        print_success(f"Installed {shell} completion to: {message}")
        click.echo()
        print_info("To activate, run one of the following:")
        click.echo(f"  source {get_shell_config_file(shell)}")
        click.echo("  # Or restart your terminal")

        if shell == "zsh":
            click.echo()
            print_info("Note: You may need to run 'compinit' to reload completions:")
            click.echo("  autoload -U compinit && compinit")
    else:
        print_error(f"Failed to install completion: {message}")


@completion_cli.command(name="uninstall")
@click.option(
    "--shell",
    type=click.Choice(["bash", "zsh", "auto"], case_sensitive=False),
    default="auto",
    help="Shell to uninstall completion from (default: auto-detect)",
)
def uninstall_completion_cmd(shell: str) -> None:
    """Uninstall shell completion.

    Examples:
        oclawma completion uninstall
        oclawma completion uninstall --shell bash
    """
    # Auto-detect shell
    if shell == "auto":
        shell = os.environ.get("SHELL", "").split("/")[-1]
        if shell not in ("bash", "zsh"):
            print_error("Could not auto-detect shell. Please specify with --shell")
            return

    success_result, message = uninstall_completion(shell)

    if success_result:
        print_success(f"Uninstalled {shell} completion from: {message}")
        print_info("Restart your terminal for changes to take effect")
    else:
        print_warning(f"Could not uninstall: {message}")


@completion_cli.command(name="show")
@click.option(
    "--shell",
    type=click.Choice(["bash", "zsh"], case_sensitive=False),
    required=True,
    help="Shell to show completion for",
)
def show_completion_cmd(shell: str) -> None:
    """Show the completion script.

    Useful for manual installation or inspection.

    Examples:
        oclawma completion show --shell bash
        oclawma completion show --shell zsh > ~/.zsh/completions/_oclawma
    """
    script = show_completion(shell)
    click.echo(script)


@completion_cli.command(name="status")
def completion_status() -> None:
    """Show completion installation status."""
    click.echo(header("SHELL COMPLETION STATUS", width=58))
    click.echo()

    for shell in ["bash", "zsh"]:
        click.echo(subheader(shell.upper()))

        path = get_completion_path(shell)
        if path and path.exists():
            print_success(f"Installed: {path}")
        else:
            print_info(f"Not installed (would be: {path})")

        config_file = get_shell_config_file(shell)
        if config_file and config_file.exists():
            click.echo(key_value("Config file", str(config_file)))
        click.echo()

    print_info("Install completion with: oclawma completion install")
