"""Tests for shell completion functionality."""

import os
import tempfile
from pathlib import Path

import pytest

from freyja import FreyjaCLI
from freyja.completion.base import CompletionContext, get_completion_handler
from freyja.completion.bash import BashCompletionHandler


# Test class for completion
class CompletionTestClass:
  """Test class for completion functionality."""

  def __init__(self, config: str = "test"):
    self.config = config

  def test_function(self, name: str = "test", count: int = 1):
    """Test function for completion.

    :param name: Name parameter
    :param count: Count parameter
    """
    print(f"Hello {name} x{count}")

  def nested_command(self, value: str = "default"):
    """Nested command for completion testing.

    :param value: Value parameter
    """
    return f"Nested: {value}"


class TestCompletionHandler:
  """Test completion handler functionality."""

  def test_get_completion_handler(self):
    """Test completion handler factory function."""
    # Create test FreyjaCLI
    cli = FreyjaCLI(CompletionTestClass, "Test FreyjaCLI")

    # Test bash handler
    handler = get_completion_handler(cli, 'bash')
    assert isinstance(handler, BashCompletionHandler)

    # Test unknown shell defaults to bash
    handler = get_completion_handler(cli, 'unknown')
    assert isinstance(handler, BashCompletionHandler)

  def test_bash_completion_handler(self):
    """Test bash completion handler."""
    cli = FreyjaCLI(CompletionTestClass, "Test FreyjaCLI")
    handler = BashCompletionHandler(cli)

    # Test script generation
    script = handler.generate_script("test_cli")
    assert "test_cli" in script
    assert "_test_cli_completion" in script
    assert "complete -F" in script

  def test_completion_context(self):
    """Test completion context creation."""
    cli = FreyjaCLI(CompletionTestClass, "Test FreyjaCLI")
    parser = cli.create_parser(no_color=True)

    context = CompletionContext(
      words=["prog", "test-function", "--name"],
      current_word="",
      cursor_position=0,
      command_group_path=["test-function"],
      parser=parser,
      cli=cli
    )

    assert context.words == ["prog", "test-function", "--name"]
    assert context.command_group_path == ["test-function"]
    assert context.cli == cli

  def test_get_available_commands(self):
    """Test getting available cmd_tree from parser."""
    cli = FreyjaCLI(CompletionTestClass, "Test FreyjaCLI")
    handler = BashCompletionHandler(cli)
    parser = cli.create_parser(no_color=True)

    commands = handler.get_available_commands(parser)
    assert "test-function" in commands
    assert "nested-command" in commands  # Single dash notation for flat commands

  def test_get_available_options(self):
    """Test getting available options from parser."""
    cli = FreyjaCLI(CompletionTestClass, "Test FreyjaCLI")
    handler = BashCompletionHandler(cli)
    parser = cli.create_parser(no_color=True)

    # Navigate to test-function command group
    subparser = handler.get_command_group_parser(parser, ["test-function"])
    assert subparser is not None

    options = handler.get_available_options(subparser)
    assert "--name" in options
    assert "--count" in options

  def test_complete_partial_word(self):
    """Test partial word completion."""
    cli = FreyjaCLI(CompletionTestClass, "Test FreyjaCLI")
    handler = BashCompletionHandler(cli)

    candidates = ["test-function", "test-command", "other-command"]

    # Test prefix matching
    result = handler.complete_partial_word(candidates, "test")
    assert result == ["test-function", "test-command"]

    # Test empty partial returns all
    result = handler.complete_partial_word(candidates, "")
    assert result == candidates

    # Test no matches
    result = handler.complete_partial_word(candidates, "xyz")
    assert result == []


class TestCompletionIntegration:
  """Test completion integration with FreyjaCLI."""

  def test_show_completion_script(self):
    """Test showing completion script via System class."""
    from freyja.cli.system import System

    # Completion functionality is now provided by System.Completion
    system = System()
    completion = system.Completion(cli_instance=None)

    # Test that completion functionality exists
    assert hasattr(completion, 'show')
    assert callable(completion.show)

class TestFileCompletion:
  """Test file path completion."""

  def test_file_path_completion(self):
    """Test file path completion functionality."""
    cli = FreyjaCLI(CompletionTestClass, "Test FreyjaCLI")
    handler = BashCompletionHandler(cli)

    # Create temporary directory with test files
    with tempfile.TemporaryDirectory() as tmpdir:
      tmpdir_path = Path(tmpdir)

      # Create test files
      (tmpdir_path / "test1.txt").touch()
      (tmpdir_path / "test2.py").touch()
      (tmpdir_path / "subdir").mkdir()

      # Change to temp directory for testing
      old_cwd = os.getcwd()
      try:
        os.chdir(tmpdir)

        # Test completing empty partial
        completions = handler._complete_file_path("")
        assert any("test1.txt" in c for c in completions)
        assert any("test2.py" in c for c in completions)
        # Directory should either end with separator or be "subdir"
        assert any("subdir" in c for c in completions)

        # Test completing partial filename
        completions = handler._complete_file_path("test")
        assert any("test1.txt" in c for c in completions)
        assert any("test2.py" in c for c in completions)

      finally:
        os.chdir(old_cwd)


if __name__ == "__main__":
  pytest.main([__file__])
