"""
Test CLI integration functionality for Issue #138: Explode Markdown file to markdown directory.

This test module covers the md-explode command integration with the existing
CLI system and command-line interface functionality.
"""

import pytest
import tempfile
import shutil
from pathlib import Path
from click.testing import CliRunner
from unittest.mock import Mock, patch

# Import will fail initially (RED phase) until implementation exists
try:
    from markitect.plugins.builtin.markdown_commands import (
        md_explode_command,
        MarkdownCommandsPlugin
    )
    from markitect.cli import cli
except ImportError:
    # Expected during RED phase - tests should fail initially
    md_explode_command = None
    MarkdownCommandsPlugin = None
    cli = None


class TestCLICommandExists:
    """Test that the md-explode command is properly registered and accessible."""

    def test_md_explode_command_function_exists(self):
        """Test that md_explode_command function exists."""
        # This should fail initially (RED phase)
        assert md_explode_command is not None
        assert callable(md_explode_command)

    def test_command_registered_in_plugin(self):
        """Test that md-explode is registered in the markdown commands plugin."""
        # This should fail initially (RED phase)

        # Check if the plugin exposes the command
        plugin = MarkdownCommandsPlugin()
        commands = plugin.get_commands()
        assert 'md-explode' in commands
        assert commands['md-explode'] == md_explode_command

    def test_command_accessible_via_cli(self):
        """Test that md-explode command is accessible through main CLI."""
        # This should fail initially (RED phase)

        runner = CliRunner()

        # Test command exists
        result = runner.invoke(cli, ['md-explode', '--help'])
        assert result.exit_code == 0
        assert 'Explode' in result.output or 'explode' in result.output


class TestCLICommandInterface:
    """Test the command-line interface of the md-explode command."""

    def setup_method(self):
        """Set up test environment."""
        self.runner = CliRunner()
        self.temp_dir = Path(tempfile.mkdtemp())

    def teardown_method(self):
        """Clean up test environment."""
        if self.temp_dir.exists():
            shutil.rmtree(self.temp_dir)

    def test_command_requires_input_file(self):
        """Test that command requires an input file argument."""
        # This should fail initially (RED phase)

        result = self.runner.invoke(cli, ['md-explode'])

        # Should fail without input file
        assert result.exit_code != 0
        assert 'input' in result.output.lower() or 'file' in result.output.lower()

    def test_command_accepts_input_file_parameter(self):
        """Test that command accepts input file parameter."""
        # This should fail initially (RED phase)

        # Create a test markdown file
        test_file = self.temp_dir / "test.md"
        test_file.write_text("# Test\nContent here.")

        # Command should accept the file
        result = self.runner.invoke(cli, ['md-explode', str(test_file)])

        # Should not fail due to missing input file
        # (may fail for other reasons during RED phase)
        assert 'input' not in result.output.lower() or result.exit_code == 0

    def test_command_supports_output_directory_option(self):
        """Test that command supports --output-dir option."""
        # This should fail initially (RED phase)

        test_file = self.temp_dir / "test.md"
        test_file.write_text("# Test\nContent here.")
        output_dir = self.temp_dir / "output"

        result = self.runner.invoke(cli, [
            'md-explode', str(test_file),
            '--output-dir', str(output_dir)
        ])

        # Should recognize the option (may fail for other reasons)
        assert 'output-dir' not in result.output or result.exit_code == 0

    def test_command_help_text(self):
        """Test that command provides comprehensive help text."""
        # This should fail initially (RED phase)

        result = self.runner.invoke(cli, ['md-explode', '--help'])

        assert result.exit_code == 0
        help_text = result.output.lower()

        # Should mention key concepts
        assert any(word in help_text for word in ['explode', 'directory', 'markdown'])
        assert any(word in help_text for word in ['input', 'file'])
        assert any(word in help_text for word in ['output', 'directory'])

    def test_command_help_includes_examples(self):
        """Test that help text includes usage examples."""
        # This should fail initially (RED phase)

        result = self.runner.invoke(cli, ['md-explode', '--help'])

        assert result.exit_code == 0
        help_text = result.output.lower()

        # Should include examples
        assert 'example' in help_text or 'usage' in help_text


class TestCLICommandExecution:
    """Test actual command execution and functionality."""

    def setup_method(self):
        """Set up test environment."""
        self.runner = CliRunner()
        self.temp_dir = Path(tempfile.mkdtemp())

    def teardown_method(self):
        """Clean up test environment."""
        if self.temp_dir.exists():
            shutil.rmtree(self.temp_dir)

    def test_command_processes_simple_markdown_file(self):
        """Test command execution with a simple markdown file."""
        # This should fail initially (RED phase)

        # Create test input
        test_content = """# Part 1: Introduction
Introduction content.

## Chapter 1: Getting Started
Chapter content.

## Chapter 2: Advanced Topics
Advanced content.
"""

        input_file = self.temp_dir / "test.md"
        input_file.write_text(test_content)

        output_dir = self.temp_dir / "exploded"

        # Execute command
        result = self.runner.invoke(cli, [
            'md-explode', str(input_file),
            '--output-dir', str(output_dir)
        ])

        # Should succeed
        assert result.exit_code == 0

        # Should create output structure
        assert output_dir.exists()
        md_files = list(output_dir.rglob("*.md"))
        assert len(md_files) > 0

    def test_command_handles_file_not_found(self):
        """Test command behavior with non-existent input file."""
        # This should fail initially (RED phase)

        non_existent_file = self.temp_dir / "nonexistent.md"

        result = self.runner.invoke(cli, [
            'md-explode', str(non_existent_file)
        ])

        # Should fail gracefully with appropriate error message
        assert result.exit_code != 0
        assert 'not found' in result.output.lower() or 'error' in result.output.lower()

    def test_command_handles_invalid_output_directory(self):
        """Test command behavior with invalid output directory."""
        # This should fail initially (RED phase)

        input_file = self.temp_dir / "test.md"
        input_file.write_text("# Test\nContent")

        invalid_output = Path("/invalid/path/that/does/not/exist")

        result = self.runner.invoke(cli, [
            'md-explode', str(input_file),
            '--output-dir', str(invalid_output)
        ])

        # Should handle error gracefully
        assert result.exit_code != 0
        error_msg = result.output.lower()
        assert any(word in error_msg for word in ['error', 'permission', 'directory', 'path'])

    def test_command_verbose_output(self):
        """Test command execution with verbose flag."""
        # This should fail initially (RED phase)

        input_file = self.temp_dir / "test.md"
        input_file.write_text("# Test\nContent")

        # Assume verbose flag exists (common pattern)
        result = self.runner.invoke(cli, [
            'md-explode', str(input_file),
            '--verbose'
        ])

        # May fail during RED phase but should handle verbose flag
        # if it exists, should show more detailed output
        if result.exit_code == 0:
            # If verbose is supported, output should be more detailed
            assert len(result.output) > 50  # Some reasonable threshold

    def test_command_dry_run_option(self):
        """Test command execution with dry-run option."""
        # This should fail initially (RED phase)

        input_file = self.temp_dir / "test.md"
        input_file.write_text("# Test\nContent")
        output_dir = self.temp_dir / "output"

        # Assume dry-run option exists (useful for this type of command)
        result = self.runner.invoke(cli, [
            'md-explode', str(input_file),
            '--output-dir', str(output_dir),
            '--dry-run'
        ])

        # During dry run, should not create actual files
        if result.exit_code == 0:
            # Should show what would be done without doing it
            assert not output_dir.exists() or len(list(output_dir.iterdir())) == 0


class TestCLICommandOptions:
    """Test various command-line options and flags."""

    def setup_method(self):
        """Set up test environment."""
        self.runner = CliRunner()
        self.temp_dir = Path(tempfile.mkdtemp())

    def teardown_method(self):
        """Clean up test environment."""
        if self.temp_dir.exists():
            shutil.rmtree(self.temp_dir)

    def test_command_supports_depth_limiting(self):
        """Test that command supports limiting the directory depth."""
        # This should fail initially (RED phase)

        input_file = self.temp_dir / "test.md"
        input_file.write_text("""
# Level 1
## Level 2
### Level 3
#### Level 4
##### Level 5
Content at level 5.
""")

        result = self.runner.invoke(cli, [
            'md-explode', str(input_file),
            '--max-depth', '3'
        ])

        # Should handle depth limiting option
        # Exact behavior depends on implementation
        if '--max-depth' in result.output:
            # Option not recognized
            assert False, "max-depth option not implemented"

    def test_command_supports_custom_file_extension(self):
        """Test that command supports custom file extensions."""
        # This should fail initially (RED phase)

        input_file = self.temp_dir / "test.md"
        input_file.write_text("# Test\nContent")

        result = self.runner.invoke(cli, [
            'md-explode', str(input_file),
            '--extension', '.txt'
        ])

        # Should handle custom extension option
        # May not be implemented initially
        if result.exit_code == 0:
            output_files = list(self.temp_dir.rglob("*.txt"))
            # If implemented, should create .txt files instead of .md