"""Enhanced tests for docscan module with new formats and performance features."""

import json

# Import module being tested
import sys
from pathlib import Path

import pytest

sys.path.insert(0, str(Path(__file__).parent.parent))
from pytola.office.docscan.docscan import DocumentScanner, Rule


class TestEnhancedFormats:
    """Test cases for enhanced file format support."""

    @pytest.fixture
    def test_rules(self):
        """Create test rules."""
        return [
            Rule(
                {
                    "name": "email",
                    "pattern": r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}",
                    "regex": True,
                    "context_lines": 1,
                }
            ),
            Rule({"name": "phone", "pattern": r"\d{3}-\d{3}-\d{4}", "regex": True, "context_lines": 1}),
        ]

    @pytest.fixture
    def test_directory(self, tmp_path):
        """Create test directory with various file formats."""
        test_dir = tmp_path / "test_docs"
        test_dir.mkdir()

        # Create test files in different formats
        files_data = [
            ("test.txt", "Contact: test@example.com, Phone: 555-123-4567"),
            ("test.json", json.dumps({"email": "test@example.com", "phone": "555-123-4567"})),
            ("test.xml", '<?xml version="1.0"?><root><email>test@example.com</email></root>'),
            ("test.html", "<html><body>Contact: test@example.com</body></html>"),
            ("test.csv", '"email","phone"\n"test@example.com","555-123-4567"'),
            ("test.md", "# Test\nContact: test@example.com"),
        ]

        for filename, content in files_data:
            (test_dir / filename).write_text(content)

        return test_dir

    def test_scanner_with_process_pool(self, test_directory, test_rules):
        """Test scanner with process pool enabled."""
        import platform

        # Skip process pool test on Windows due to multiprocessing issues
        if platform.system() == "Windows":
            pytest.skip("Process pool test skipped on Windows")

        scanner = DocumentScanner(
            test_directory, test_rules, ["txt", "json", "xml"], use_process_pool=True, batch_size=10
        )

        assert scanner.use_process_pool is True
        assert scanner.batch_size == 10

        # Run scan (note: may not work in all test environments)
        try:
            results = scanner.scan(threads=2)
            assert "scan_info" in results
            assert "use_process_pool" in results["scan_info"]
            assert results["scan_info"]["use_process_pool"] is True
        except Exception as e:
            # Process pool may not work in test environment
            pytest.skip(f"Process pool not available in test environment: {e}")

    def test_scan_json_files(self, test_directory, test_rules):
        """Test scanning JSON files."""
        scanner = DocumentScanner(test_directory, test_rules, ["json"])

        results = scanner.scan(threads=1)
        json_matches = [m for m in results["matches"] if m["file_type"] == "json"]

        assert len(json_matches) >= 1
        assert any("example.com" in str(match) for match in json_matches)

    def test_scan_xml_files(self, test_directory, test_rules):
        """Test scanning XML files."""
        scanner = DocumentScanner(test_directory, test_rules, ["xml"])

        results = scanner.scan(threads=1)
        xml_matches = [m for m in results["matches"] if m["file_type"] == "xml"]

        assert len(xml_matches) >= 1

    def test_scan_html_files(self, test_directory, test_rules):
        """Test scanning HTML files."""
        scanner = DocumentScanner(test_directory, test_rules, ["html"])

        results = scanner.scan(threads=1)
        html_matches = [m for m in results["matches"] if m["file_type"] == "html"]

        assert len(html_matches) >= 1

    def test_scan_csv_files(self, test_directory, test_rules):
        """Test scanning CSV files."""
        scanner = DocumentScanner(test_directory, test_rules, ["csv"])

        results = scanner.scan(threads=1)
        csv_matches = [m for m in results["matches"] if m["file_type"] == "csv"]

        assert len(csv_matches) >= 1

    def test_scan_markdown_files(self, test_directory, test_rules):
        """Test scanning Markdown files."""
        scanner = DocumentScanner(test_directory, test_rules, ["md"])

        results = scanner.scan(threads=1)
        md_matches = [m for m in results["matches"] if m["file_type"] == "md"]

        assert len(md_matches) >= 1

    def test_scan_multiple_formats(self, test_directory, test_rules):
        """Test scanning files in multiple formats simultaneously."""
        scanner = DocumentScanner(test_directory, test_rules, ["txt", "json", "xml", "html", "csv", "md"])

        results = scanner.scan(threads=1)

        # Verify files of different types were scanned
        file_types = {m["file_type"] for m in results["matches"]}
        assert len(file_types) >= 2  # At least 2 different formats found matches


class TestPerformanceFeatures:
    """Test cases for performance features."""

    def test_batch_size_parameter(self, tmp_path):
        """Test batch size parameter."""
        test_dir = tmp_path / "test"
        test_dir.mkdir()
        (test_dir / "test.txt").write_text("Contact: test@example.com")

        rules = [Rule({"name": "email", "pattern": r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}", "regex": True})]

        scanner = DocumentScanner(test_dir, rules, ["txt"], batch_size=100)
        assert scanner.batch_size == 100

        results = scanner.scan(threads=1)
        assert "scan_info" in results

    def test_process_pool_vs_thread_pool(self, tmp_path):
        """Test both process pool and thread pool work."""
        import platform

        # Skip process pool test on Windows due to multiprocessing issues
        if platform.system() == "Windows":
            pytest.skip("Process pool test skipped on Windows")

        test_dir = tmp_path / "test"
        test_dir.mkdir()

        # Create test files
        for i in range(5):
            (test_dir / f"test{i}.txt").write_text(f"Contact: user{i}@example.com")

        rules = [Rule({"name": "email", "pattern": r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}", "regex": True})]

        # Test with thread pool
        scanner_thread = DocumentScanner(test_dir, rules, ["txt"], use_process_pool=False)
        results_thread = scanner_thread.scan(threads=2)
        assert results_thread["scan_info"]["use_process_pool"] is False

        # Test with process pool (may skip in some environments)
        scanner_process = DocumentScanner(test_dir, rules, ["txt"], use_process_pool=True)
        try:
            results_process = scanner_process.scan(threads=2)
            assert results_process["scan_info"]["use_process_pool"] is True
        except Exception:
            # Process pool may not work in test environment
            pytest.skip("Process pool not available in test environment")


class TestComprehensiveRules:
    """Test cases for comprehensive rules."""

    @pytest.fixture
    def comprehensive_rules(self):
        """Load comprehensive rules from file."""
        rules_file = Path(__file__).parent.parent / "rules_comprehensive.json"
        if not rules_file.exists():
            pytest.skip("rules_comprehensive.json not found")

        with open(rules_file) as f:
            rules_data = json.load(f)

        return [Rule(rule) for rule in rules_data["rules"]]

    def test_all_rules_compilable(self, comprehensive_rules):
        """Test that all comprehensive rules are compilable."""
        assert len(comprehensive_rules) > 0

        for rule in comprehensive_rules:
            assert rule.name
            assert rule.pattern

            # Test that regex rules are compilable
            if rule.is_regex:
                assert rule.compiled_pattern is not None, f"Rule '{rule.name}' failed to compile"

    def test_email_rule(self, comprehensive_rules):
        """Test email rule from comprehensive set."""
        email_rule = next((r for r in comprehensive_rules if r.name == "email_addresses"), None)
        assert email_rule is not None

        test_text = "Contact: john.doe@example.com or support@company.org"
        matches = email_rule.search(test_text)

        assert len(matches) >= 2
        assert "example.com" in matches[0]["match"]
        assert "company.org" in matches[1]["match"]

    def test_url_rule(self, comprehensive_rules):
        """Test URL rule from comprehensive set."""
        url_rule = next((r for r in comprehensive_rules if r.name == "url_links"), None)
        assert url_rule is not None

        test_text = "Visit: https://www.example.com or http://docs.example.com"
        matches = url_rule.search(test_text)

        assert len(matches) >= 2
        assert "https://www.example.com" in matches[0]["match"]

    def test_currency_rule(self, comprehensive_rules):
        """Test currency rule from comprehensive set."""
        currency_rule = next((r for r in comprehensive_rules if r.name == "currency_amounts"), None)
        assert currency_rule is not None

        test_text = "Price: $1,234.56 and Discount: $987.65"
        matches = currency_rule.search(test_text)

        assert len(matches) >= 2
        assert "$1,234.56" in matches[0]["match"]

    def test_version_rule(self, comprehensive_rules):
        """Test version number rule from comprehensive set."""
        version_rule = next((r for r in comprehensive_rules if r.name == "version_numbers"), None)
        assert version_rule is not None

        test_text = "Version v2.1.3-beta and Version 3.0.0"
        matches = version_rule.search(test_text)

        assert len(matches) >= 2


class TestErrorHandlingEnhanced:
    """Enhanced error handling tests."""

    def test_missing_library_graceful_degradation(self, tmp_path):
        """Test graceful degradation when optional libraries are missing."""
        test_dir = tmp_path / "test"
        test_dir.mkdir()

        # Create a simple text file (always supported)
        (test_dir / "test.txt").write_text("Contact: test@example.com")

        rules = [Rule({"name": "email", "pattern": r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}", "regex": True})]

        scanner = DocumentScanner(test_dir, rules, ["txt", "epub", "odt"])

        # Should work even if epub/odt libraries are not installed
        results = scanner.scan(threads=1)

        assert "scan_info" in results
        # At least the TXT file should be scanned
        assert results["scan_info"]["total_files"] >= 1


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