"""Zsh shell completion handler."""

import sys

from .base import CompletionContext, CompletionHandler


class ZshCompletionHandler(CompletionHandler):
  """Zsh-specific completion handler."""

  def generate_script(self, prog_name: str, command_patterns: list[str] = None) -> str:
    """Generate zsh 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('.', '_')

    # Build script with proper pattern-based registration
    script = f'''#compdef {prog_basename}
# Zsh completion for {prog_basename} and related command patterns
# Generated by freyja

_{func_name}() {{
    # Get the actual command being completed (first word)
    # Extract basename to handle path-based invocations (e.g., examples/cls_example)
    local prog="${{words[1]}}"
    local prog_basename="${{prog:t}}"  # :t modifier extracts basename

    # Call the program to get completions
    local -a completions
    # Check if file looks like a Python script by examining its content or extension
    local use_python=false
    if [[ "${{prog}}" == *.py ]] || [[ ! -x "${{prog}}" ]]; then
        use_python=true
    elif [[ -f "${{prog}}" ]]; then
        # Check if file starts with python shebang
        local first_line=$(head -n1 "${{prog}}" 2>/dev/null)
        if [[ "$first_line" == *"python"* ]]; then
            use_python=true
        fi
    fi

    # Set completion environment variables inline to prevent shell persistence
    if [[ "$use_python" == true ]]; then
        # For Python scripts, use python interpreter
        completions=($(
            _FREYJA_COMPLETE=zsh \\
            COMP_WORDS_STR="${{words[@]}}" \\
            COMP_CWORD_NUM=${{#words[@]}} \\
            PYTHONPATH=. python "${{prog}}" --_complete 2>/dev/null
        ))
    else
        # For direct executables
        completions=($(
            _FREYJA_COMPLETE=zsh \\
            COMP_WORDS_STR="${{words[@]}}" \\
            COMP_CWORD_NUM=${{#words[@]}} \\
            PYTHONPATH=. "${{prog}}" --_complete 2>/dev/null
        ))
    fi

    # Add completions if we got any
    if [[ $#completions -gt 0 ]]; then
        compadd -a completions
    fi
}}

# Register completion for the base command name
compdef _{func_name} {prog_basename}

# Register completion for path-based invocations using pattern matching
# This handles cases like: examples/{prog_basename}, ./bin/{prog_basename}, /usr/local/bin/{prog_basename}
compdef _{func_name} "*/{prog_basename}"

# Register completion for nested path invocations
compdef _{func_name} "**/{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'\ncompdef _{func_name} {pattern_basename}'
            script += f'\ncompdef _{func_name} "*/{pattern_basename}"'

    return script

  def get_completions(self, context: CompletionContext) -> list[str]:
    """Get zsh-specific completions."""
    # Reuse bash completion logic for now
    from .bash import BashCompletionHandler
    bash_handler = BashCompletionHandler(self.cli)
    return bash_handler._get_generic_completions(context)

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


def handle_zsh_completion() -> None:
  """Handle zsh completion request from environment variables."""
  # This function should not be called anymore
  # Completion is handled through the ExecutionCoordinator._handle_completion_request
  # But for compatibility, if we somehow reach here, just exit cleanly
  sys.exit(0)
