"""
TDD8 Cycle 3: Contentmatter Commands Tests (RED Phase)
Issue #38 - MarkdownMatters CLI Implementation

This test file implements the RED phase tests for contentmatter command family:
- markitect contentmatter-get [key] [path] - Get MMD key-value from content
- markitect contentmatter-set key=value [path] - Set MMD key-value in content
- markitect contentmatter-keys [path] - List all contentmatter keys
- markitect contentmatter-stats [path] - Contentmatter statistics

Following TDD8 methodology, these tests MUST FAIL initially.
"""

import pytest
import tempfile
import os
from pathlib import Path
from click.testing import CliRunner

from markitect.matter_contentmatter.parser import ContentmatterParser
from markitect.matter_contentmatter.stats import ContentmatterStats
from markitect.matter_contentmatter.commands import contentmatter_get, contentmatter_set, contentmatter_keys, contentmatter_stats


class TestContentmatterExtraction:
    """Test contentmatter extraction and parsing."""

    @pytest.fixture
    def test_files_dir(self):
        """Path to contentmatter test fixture files."""
        return Path(__file__).parent / "fixtures" / "contentmatter_test_files"

    @pytest.fixture
    def contentmatter_parser(self):
        """Contentmatter parser instance."""
        return ContentmatterParser()

    def test_contentmatter_parser_extracts_mmd_keyvalues(self, contentmatter_parser, test_files_dir):
        """Test that parser extracts MultiMarkdown key-value pairs."""
        file_path = test_files_dir / "simple_contentmatter.md"

        with open(file_path, 'r') as f:
            text = f.read()

        contentmatter = contentmatter_parser.extract_contentmatter(text)

        # Should extract basic key-value pairs
        assert contentmatter["Author"] == "Jane Smith"
        assert contentmatter["Project"] == "Contentmatter Testing"
        assert contentmatter["Version"] == "2.0"
        assert contentmatter["Status"] == "Active"
        assert contentmatter["License"] == "MIT"
        assert contentmatter["Repository"] == "https://github.com/example/project"
        assert contentmatter["Documentation"] == "https://docs.example.com"
        assert contentmatter["Updated"] == "2025-10-02"
        assert contentmatter["Reviewer"] == "John Doe"
        assert contentmatter["Category"] == "Testing"

    def test_contentmatter_parser_extracts_complex_content(self, contentmatter_parser, test_files_dir):
        """Test extraction from document with rich contentmatter."""
        file_path = test_files_dir / "mmd_rich_content.md"

        with open(file_path, 'r') as f:
            text = f.read()

        contentmatter = contentmatter_parser.extract_contentmatter(text)

        # Should extract author information
        assert contentmatter["Author"] == "Dr. Sarah Johnson"
        assert contentmatter["Institution"] == "MIT Computer Science Department"
        assert contentmatter["Email"] == "sarah.johnson@mit.edu"

        # Should extract research metadata
        assert contentmatter["Keywords"] == "algorithms, distributed systems, optimization, performance"
        assert contentmatter["Classification"] == "Computer Science - Distributed Computing"
        assert contentmatter["Grant Number"] == "NSF-CS-2025-001"

        # Should extract methodology details
        assert contentmatter["Research Method"] == "Experimental Analysis"
        assert contentmatter["Sample Size"] == "1000 distributed nodes"
        assert contentmatter["Performance Improvement"] == "23% average speedup"

    def test_contentmatter_parser_handles_no_contentmatter(self, contentmatter_parser, test_files_dir):
        """Test that parser handles documents without contentmatter."""
        file_path = test_files_dir / "no_contentmatter.md"

        with open(file_path, 'r') as f:
            text = f.read()

        contentmatter = contentmatter_parser.extract_contentmatter(text)

        # Should return empty dict for no contentmatter
        assert contentmatter == {}

    def test_contentmatter_parser_ignores_frontmatter_and_tailmatter(self, contentmatter_parser, test_files_dir):
        """Test that parser only extracts from content, not matter zones."""
        file_path = test_files_dir / "mmd_rich_content.md"

        with open(file_path, 'r') as f:
            text = f.read()

        contentmatter = contentmatter_parser.extract_contentmatter(text)

        # Should not include frontmatter values
        assert "title" not in contentmatter  # This is in frontmatter
        assert "qa_checklist" not in contentmatter  # This is in tailmatter

        # Should only include content key-values
        assert "Author" in contentmatter  # This is in content

    def test_contentmatter_get_specific_value(self, contentmatter_parser, test_files_dir):
        """Test getting specific contentmatter values."""
        file_path = test_files_dir / "simple_contentmatter.md"

        with open(file_path, 'r') as f:
            text = f.read()

        value = contentmatter_parser.get_contentmatter_value(text, "Author")
        assert value == "Jane Smith"

        value = contentmatter_parser.get_contentmatter_value(text, "Repository")
        assert value == "https://github.com/example/project"

        # Should return None for non-existent keys
        value = contentmatter_parser.get_contentmatter_value(text, "NonExistent")
        assert value is None


class TestContentmatterModification:
    """Test contentmatter modification operations."""

    @pytest.fixture
    def contentmatter_parser(self):
        """Contentmatter parser instance."""
        return ContentmatterParser()

    def test_contentmatter_set_new_value(self, contentmatter_parser):
        """Test adding new contentmatter to document."""
        text = """# Test Document

Some content here.

## Section

More content."""

        new_text = contentmatter_parser.set_contentmatter_value(text, "Author", "New Author")

        # Should add the contentmatter
        contentmatter = contentmatter_parser.extract_contentmatter(new_text)
        assert contentmatter["Author"] == "New Author"

        # Should preserve original content
        assert "# Test Document" in new_text
        assert "Some content here." in new_text

    def test_contentmatter_update_existing_value(self, contentmatter_parser):
        """Test updating existing contentmatter value."""
        text = """# Test Document

Author: Original Author
Project: Test Project

Some content here."""

        new_text = contentmatter_parser.set_contentmatter_value(text, "Author", "Updated Author")

        # Should update the existing value
        contentmatter = contentmatter_parser.extract_contentmatter(new_text)
        assert contentmatter["Author"] == "Updated Author"
        assert contentmatter["Project"] == "Test Project"  # Should preserve other values

    def test_contentmatter_set_multiple_values(self, contentmatter_parser):
        """Test setting multiple contentmatter values."""
        text = """# Test Document

Some content here."""

        # Add multiple values
        text = contentmatter_parser.set_contentmatter_value(text, "Author", "Test Author")
        text = contentmatter_parser.set_contentmatter_value(text, "Version", "1.0")
        text = contentmatter_parser.set_contentmatter_value(text, "Status", "Active")

        contentmatter = contentmatter_parser.extract_contentmatter(text)
        assert contentmatter["Author"] == "Test Author"
        assert contentmatter["Version"] == "1.0"
        assert contentmatter["Status"] == "Active"


class TestContentmatterKeys:
    """Test contentmatter key listing functionality."""

    @pytest.fixture
    def test_files_dir(self):
        """Path to contentmatter test fixture files."""
        return Path(__file__).parent / "fixtures" / "contentmatter_test_files"

    @pytest.fixture
    def contentmatter_parser(self):
        """Contentmatter parser instance."""
        return ContentmatterParser()

    def test_contentmatter_keys_simple_document(self, contentmatter_parser, test_files_dir):
        """Test listing keys from simple contentmatter document."""
        file_path = test_files_dir / "simple_contentmatter.md"

        with open(file_path, 'r') as f:
            text = f.read()

        keys = contentmatter_parser.get_contentmatter_keys(text)

        # Should return all contentmatter keys
        expected_keys = ["Author", "Project", "Version", "Status", "License", "Repository", "Documentation", "Updated", "Reviewer", "Category"]
        assert set(keys) == set(expected_keys)

    def test_contentmatter_keys_complex_document(self, contentmatter_parser, test_files_dir):
        """Test listing keys from complex contentmatter document."""
        file_path = test_files_dir / "mmd_rich_content.md"

        with open(file_path, 'r') as f:
            text = f.read()

        keys = contentmatter_parser.get_contentmatter_keys(text)

        # Should include research paper metadata keys
        assert "Author" in keys
        assert "Institution" in keys
        assert "Keywords" in keys
        assert "Research Method" in keys
        assert "Performance Improvement" in keys

        # Should not include frontmatter or tailmatter keys
        assert "title" not in keys  # frontmatter
        assert "qa_checklist" not in keys  # tailmatter

    def test_contentmatter_keys_empty_document(self, contentmatter_parser, test_files_dir):
        """Test listing keys from document without contentmatter."""
        file_path = test_files_dir / "no_contentmatter.md"

        with open(file_path, 'r') as f:
            text = f.read()

        keys = contentmatter_parser.get_contentmatter_keys(text)

        # Should return empty list
        assert keys == []


class TestContentmatterStatistics:
    """Test contentmatter statistics calculation."""

    @pytest.fixture
    def test_files_dir(self):
        """Path to contentmatter test fixture files."""
        return Path(__file__).parent / "fixtures" / "contentmatter_test_files"

    @pytest.fixture
    def contentmatter_parser(self):
        """Contentmatter parser instance."""
        return ContentmatterParser()

    def test_contentmatter_stats_simple_document(self, contentmatter_parser, test_files_dir):
        """Test statistics calculation for simple contentmatter."""
        file_path = test_files_dir / "simple_contentmatter.md"

        with open(file_path, 'r') as f:
            text = f.read()

        stats = contentmatter_parser.calculate_contentmatter_stats(text)

        # Should count contentmatter correctly
        assert stats.total_pairs == 10  # Number of key-value pairs
        assert stats.has_contentmatter is True
        assert stats.average_key_length > 0
        assert stats.average_value_length > 0

        # Should categorize value types
        assert stats.url_values > 0  # Repository and Documentation URLs
        assert stats.date_values > 0  # Updated field
        assert stats.email_values == 0  # No email in simple document

    def test_contentmatter_stats_complex_document(self, contentmatter_parser, test_files_dir):
        """Test statistics calculation for complex contentmatter."""
        file_path = test_files_dir / "mmd_rich_content.md"

        with open(file_path, 'r') as f:
            text = f.read()

        stats = contentmatter_parser.calculate_contentmatter_stats(text)

        # Should count rich contentmatter
        assert stats.total_pairs > 15  # Many key-value pairs in research paper
        assert stats.has_contentmatter is True

        # Should detect email values
        assert stats.email_values > 0  # Email field in author info

    def test_contentmatter_stats_no_contentmatter(self, contentmatter_parser, test_files_dir):
        """Test statistics for document without contentmatter."""
        file_path = test_files_dir / "no_contentmatter.md"

        with open(file_path, 'r') as f:
            text = f.read()

        stats = contentmatter_parser.calculate_contentmatter_stats(text)

        # Should indicate no contentmatter
        assert stats.has_contentmatter is False
        assert stats.total_pairs == 0
        assert stats.url_values == 0
        assert stats.email_values == 0


class TestContentmatterCLICommands:
    """Test CLI command integration."""

    @pytest.fixture
    def runner(self):
        """CLI test runner."""
        return CliRunner()

    @pytest.fixture
    def test_files_dir(self):
        """Path to contentmatter test fixture files."""
        return Path(__file__).parent / "fixtures" / "contentmatter_test_files"

    def test_contentmatter_get_command(self, runner, test_files_dir):
        """Test contentmatter-get CLI command."""
        file_path = test_files_dir / "simple_contentmatter.md"

        # Test getting simple value
        result = runner.invoke(contentmatter_get, ['Author', '--file', str(file_path)])
        assert result.exit_code == 0
        assert "Jane Smith" in result.output

        # Test getting URL value
        result = runner.invoke(contentmatter_get, ['Repository', '--file', str(file_path)])
        assert result.exit_code == 0
        assert "https://github.com/example/project" in result.output

    def test_contentmatter_keys_command(self, runner, test_files_dir):
        """Test contentmatter-keys CLI command."""
        file_path = test_files_dir / "simple_contentmatter.md"

        result = runner.invoke(contentmatter_keys, ['--file', str(file_path)])
        assert result.exit_code == 0
        assert "Author" in result.output
        assert "Project" in result.output
        assert "Repository" in result.output

    def test_contentmatter_stats_command(self, runner, test_files_dir):
        """Test contentmatter-stats CLI command."""
        file_path = test_files_dir / "simple_contentmatter.md"

        result = runner.invoke(contentmatter_stats, ['--file', str(file_path)])
        assert result.exit_code == 0
        assert "total_pairs" in result.output
        assert "has_contentmatter" in result.output

    def test_contentmatter_set_command(self, runner, test_files_dir):
        """Test contentmatter-set CLI command."""
        # Create temporary file for testing
        with tempfile.NamedTemporaryFile(mode='w', suffix='.md', delete=False) as f:
            f.write("""# Test Document

Author: Original Author

Some content here.""")
            temp_file = f.name

        try:
            result = runner.invoke(contentmatter_set, ['Author=New Author', '--file', temp_file])
            assert result.exit_code == 0

            # Verify the change was made
            with open(temp_file, 'r') as f:
                content = f.read()
                assert "Author: New Author" in content

        finally:
            os.unlink(temp_file)

    def test_contentmatter_commands_help_text(self, runner):
        """Test that help text is available for all contentmatter commands."""
        commands = [contentmatter_get, contentmatter_keys, contentmatter_stats, contentmatter_set]

        for command in commands:
            result = runner.invoke(command, ['--help'])
            assert result.exit_code == 0
            assert "contentmatter" in result.output.lower()


class TestContentmatterStats:
    """Test ContentmatterStats data class."""

    def test_contentmatter_stats_creation(self):
        """Test ContentmatterStats object creation."""
        stats = ContentmatterStats(
            has_contentmatter=True,
            total_pairs=10,
            average_key_length=8.5,
            average_value_length=15.2,
            url_values=2,
            email_values=1,
            date_values=1
        )

        assert stats.has_contentmatter is True
        assert stats.total_pairs == 10
        assert stats.average_key_length == 8.5
        assert stats.url_values == 2

    def test_contentmatter_stats_to_dict(self):
        """Test ContentmatterStats conversion to dictionary."""
        stats = ContentmatterStats(
            has_contentmatter=True,
            total_pairs=5,
            average_key_length=8.0,
            average_value_length=12.0,
            url_values=1,
            email_values=0,
            date_values=1
        )

        stats_dict = stats.to_dict()

        assert stats_dict["has_contentmatter"] is True
        assert stats_dict["total_pairs"] == 5
        assert stats_dict["url_values"] == 1