"""Bash shell completion handler."""

import os
import sys

from .base import CompletionContext, CompletionHandler


class BashCompletionHandler(CompletionHandler):
  """Bash-specific completion handler."""

  def generate_script(self, prog_name: str, command_patterns: list[str] = None) -> str:
    """Generate bash completion script with pattern-based registration for path invocations.

    :param prog_name: Base program name
    :param command_patterns: Additional command patterns to register completion for
    """
    from pathlib import Path

    # Always use basename for consistency - this fixes path-based invocation issues
    prog_basename = Path(prog_name).name
    func_name = prog_basename.replace('-', '_').replace('.', '_')

    script = f'''#!/bin/bash
# Bash completion for {prog_basename} and related command patterns
# Generated by freyja

_{func_name}_completion()
{{
    local cur prev opts
    COMPREPLY=()
    cur="${{COMP_WORDS[COMP_CWORD]}}"
    prev="${{COMP_WORDS[COMP_CWORD-1]}}"

    # Get the actual command being completed (first word)
    # Extract basename to handle path-based invocations (e.g., examples/{prog_basename})
    local prog="${{COMP_WORDS[0]}}"
    local prog_basename="$(basename "$prog")"

    # Get completions from the program with inline environment variables to prevent shell persistence
    local completions
    # Check if this looks like a Python script
    if [[ "$prog" == *.py ]] || [[ ! -x "$prog" ]] || [[ -f "$prog" && "$(head -n1 "$prog" 2>/dev/null)" == *"python"* ]]; then
        # For Python scripts, use python interpreter
        completions=$(
            _FREYJA_COMPLETE=bash \\
            COMP_WORDS_STR="${{COMP_WORDS[@]}}" \\
            COMP_CWORD_NUM=${{COMP_CWORD}} \\
            PYTHONPATH=. python "$prog" --_complete 2>/dev/null
        )
    else
        # For direct executables
        completions=$(
            _FREYJA_COMPLETE=bash \\
            COMP_WORDS_STR="${{COMP_WORDS[@]}}" \\
            COMP_CWORD_NUM=${{COMP_CWORD}} \\
            PYTHONPATH=. "$prog" --_complete 2>/dev/null
        )
    fi

    if [ $? -eq 0 ]; then
        COMPREPLY=($(compgen -W "${{completions}}" -- "${{cur}}"))
    fi

    return 0
}}

# Register completion for the base command name
complete -F _{func_name}_completion {prog_basename}

# Register completion for path-based invocations
# This handles cases like: examples/{prog_basename}, ./bin/{prog_basename}, /usr/local/bin/{prog_basename}
complete -F _{func_name}_completion "./{prog_basename}"
complete -F _{func_name}_completion "*/{prog_basename}"'''

    # Add registration for additional command patterns if provided
    if command_patterns:
        for pattern in command_patterns:
            pattern_basename = Path(pattern).name
            script += f'\n\n# Additional pattern: {pattern}'
            script += f'\ncomplete -F _{func_name}_completion {pattern_basename}'
            script += f'\ncomplete -F _{func_name}_completion "*/{pattern_basename}"'

    return script

  def get_completions(self, context: CompletionContext) -> list[str]:
    """Get bash-specific completions."""
    return self._get_generic_completions(context)

  def install_completion(self, prog_name: str) -> bool:
    """Install bash completion."""
    from .installer import CompletionInstaller
    installer = CompletionInstaller(self, prog_name)
    return installer.install('bash')

  def _get_generic_completions(self, context: CompletionContext) -> list[str]:
    """Get generic completions that work across shells."""
    completions = []

    # Get the appropriate parser for current context
    parser = context.parser
    if context.command_group_path:
      parser = self.get_command_group_parser(parser, context.command_group_path)
      if not parser:
        return []

    # Determine what we're completing
    current_word = context.current_word

    # Check if we're completing an option value
    if len(context.words) >= 2:
      prev_word = context.words[-2] if len(context.words) >= 2 else ""

      # If previous word is an option, complete its values
      if prev_word.startswith('--'):
        option_values = self.get_option_values(parser, prev_word, current_word)
        if option_values:
          return option_values

    # Complete options if current word starts with --
    if current_word.startswith('--'):
      options = self.get_available_options(parser)
      return self.complete_partial_word(options, current_word)

    # Complete cmd_tree/command groups
    commands = self.get_available_commands(parser)
    if commands:
      return self.complete_partial_word(commands, current_word)

    return completions


def handle_bash_completion() -> None:
  """Handle bash completion request from environment variables."""
  if os.environ.get('_FREYJA_COMPLETE') != 'bash':
    return

  # Parse completion context from environment
  words_str = os.environ.get('COMP_WORDS_STR', '')
  cword_num = int(os.environ.get('COMP_CWORD_NUM', '0'))

  if not words_str:
    return

  words = words_str.split()
  if not words or cword_num >= len(words):
    return

  current_word = words[cword_num] if cword_num < len(words) else ""

  # Extract command group path (everything between program name and current word)
  command_group_path = []
  if len(words) > 1:
    for i in range(1, min(cword_num, len(words))):
      word = words[i]
      if not word.startswith('-'):
        command_group_path.append(word)

  # Import here to avoid circular imports

  # This would need to be set up by the FreyjaCLI instance
  # For now, just output basic completions
  print("--help --verbose --no-color")
  sys.exit(0)
