"""Test suite for enhanced debug mode functionality in pyloadergen."""

from __future__ import annotations

import logging
from unittest import mock

import pytest

from ..components.loader import (
    _MACOS_GUI_TEMPLATE,
    _UNIX_CONSOLE_TEMPLATE,
    _WINDOWS_GUI_TEMPLATE,
    PyLoaderGenerator,
    logger,
    prepare_c_source,
)


class TestEnhancedDebugMode:
    """Test enhanced debug mode features."""

    def test_debug_mode_logging_enhancement(self, tmp_path):
        """Test that debug mode provides enhanced logging information."""
        # Create a minimal project structure
        project_dir = tmp_path / "test_project"
        project_dir.mkdir()

        # Create pyproject.toml
        pyproject = project_dir / "pyproject.toml"
        pyproject.write_text("""
[project]
name = "test-project"
version = "1.0.0"
description = "Test project"
dependencies = []

[project.scripts]
test-project = "test_project.main:main"
""")

        # Create main.py with entry point
        main_py = project_dir / "main.py"
        main_py.write_text("""
def main():
    print("Hello from test project")

if __name__ == "__main__":
    main()
""")

        # Mock the compilation process to capture debug output
        with mock.patch("pytola.dev.pypack.components.loader.find_compiler", return_value="gcc"), mock.patch(
            "pytola.dev.pypack.components.loader.compile_c_source", return_value=True
        ):
            # Capture logs
            log_capture = []

            class LogCaptureHandler(logging.Handler):
                def emit(self, record):
                    log_capture.append(record.getMessage())

            handler = LogCaptureHandler()
            logger.addHandler(handler)
            original_level = logger.level
            logger.setLevel(logging.DEBUG)

            try:
                # Run with debug mode
                generator = PyLoaderGenerator(root_dir=project_dir)
                generator.generate_for_project(
                    project=next(iter(generator.solution.projects.values())),
                    project_dir=project_dir,
                    debug=True,
                )

                # Verify debug logs contain enhanced information
                debug_logs = [log for log in log_capture if "DEBUG MODE" in log]
                assert len(debug_logs) > 0, "Should have debug mode logs"

                # Check for specific enhanced debug information
                assert any("C Source Generation" in log for log in debug_logs)
                assert any("Build Summary" in log for log in debug_logs)
            finally:
                logger.removeHandler(handler)
                logger.setLevel(original_level)

    def test_debug_mode_c_source_generation(self):
        """Test that debug mode C source contains enhanced debug information."""
        # Test Windows GUI template with debug mode
        template = _WINDOWS_GUI_TEMPLATE
        entry_file = "test_app.ent"
        is_debug = True

        c_code = prepare_c_source(template, entry_file, is_debug)

        # Check for enhanced debug sections in generated C code
        assert "DEBUG MODE - Application Startup" in c_code
        assert "DEBUG MODE - Command Construction" in c_code
        assert "DEBUG MODE - Process Creation" in c_code
        assert "DEBUG MODE - Process Exit" in c_code
        assert "DEBUG MODE - Application Error Details" in c_code

        # Check for enhanced error reporting
        assert "Error output length" in c_code
        assert "Message truncation threshold" in c_code
        assert "Full error details saved to: error_details.txt" in c_code

        # Check for process information
        assert "Process ID" in c_code
        assert "Thread ID" in c_code
        assert "Exit code interpretation" in c_code

    def test_debug_mode_unix_templates(self):
        """Test Unix templates have enhanced debug information."""
        # Test Unix console template
        template = _UNIX_CONSOLE_TEMPLATE
        entry_file = "test_app.ent"
        is_debug = True

        c_code = prepare_c_source(template, entry_file, is_debug)

        # Check for Unix-specific debug enhancements
        assert "DEBUG MODE - Exit Code Analysis" in c_code
        assert "Process exit status" in c_code
        assert "Exited normally" in c_code
        assert "Terminated by signal" in c_code

        # Check for signal analysis
        assert "Signal description" in c_code
        assert "Segmentation fault" in c_code
        assert "Aborted" in c_code

    def test_debug_mode_macos_templates(self):
        """Test macOS templates have enhanced debug information."""
        # Test macOS GUI template
        template = _MACOS_GUI_TEMPLATE
        entry_file = "test_app.ent"
        is_debug = True

        c_code = prepare_c_source(template, entry_file, is_debug)

        # Check that debug mode is enabled (macro substitution)
        assert "#if 1" in c_code  # Debug mode enabled
        assert "DEBUG MODE" in c_code

    def test_debug_mode_error_handling_enhancement(self, tmp_path):
        """Test enhanced error handling in debug mode."""
        project_dir = tmp_path / "error_test"
        project_dir.mkdir()

        pyproject = project_dir / "pyproject.toml"
        pyproject.write_text("""
[project]
name = "error-test"
version = "1.0.0"
description = "Test project with errors"
dependencies = []
""")

        main_py = project_dir / "main.py"
        main_py.write_text("""
def main():
    raise RuntimeError("Test error for debug mode")

if __name__ == "__main__":
    main()
""")

        # Mock compilation to succeed but simulate runtime error
        with mock.patch("pytola.dev.pypack.components.loader.find_compiler", return_value="gcc"), mock.patch(
            "pytola.dev.pypack.components.loader.compile_c_source", return_value=True
        ):
            log_capture = []

            class LogCaptureHandler(logging.Handler):
                def emit(self, record):
                    log_capture.append(record.getMessage())

            handler = LogCaptureHandler()
            logger.addHandler(handler)
            original_level = logger.level
            logger.setLevel(logging.DEBUG)

            try:
                generator = PyLoaderGenerator(root_dir=project_dir)
                # This should generate the loader successfully
                success = generator.generate_for_project(
                    project=next(iter(generator.solution.projects.values())),
                    project_dir=project_dir,
                    debug=True,
                )
                assert success is True

                # Check that debug logs show build completion details
                debug_logs = [log for log in log_capture if "DEBUG MODE" in log]
                build_summary_logs = [log for log in debug_logs if "Build Summary" in log]
                assert len(build_summary_logs) > 0

                # Verify build summary contains debug information
                summary_text = " ".join(build_summary_logs)
                assert "DEBUG MODE" in summary_text
                # Note: The actual log output uses "DEBUG MODE" (all caps), not "Debug mode"

            finally:
                logger.removeHandler(handler)
                logger.setLevel(original_level)

    def test_debug_mode_performance_timing(self, tmp_path):
        """Test that debug mode includes performance timing information."""
        project_dir = tmp_path / "timing_test"
        project_dir.mkdir()

        pyproject = project_dir / "pyproject.toml"
        pyproject.write_text("""
[project]
name = "timing-test"
version = "1.0.0"
description = "Timing test project"
dependencies = []
""")

        main_py = project_dir / "main.py"
        main_py.write_text("""
def main():
    pass

if __name__ == "__main__":
    main()
""")

        with mock.patch("pytola.dev.pypack.components.loader.find_compiler", return_value="gcc"), mock.patch(
            "pytola.dev.pypack.components.loader.compile_c_source", return_value=True
        ):
            log_capture = []

            class LogCaptureHandler(logging.Handler):
                def emit(self, record):
                    log_capture.append(record.getMessage())

            handler = LogCaptureHandler()
            logger.addHandler(handler)
            original_level = logger.level
            logger.setLevel(logging.DEBUG)

            try:
                generator = PyLoaderGenerator(root_dir=project_dir)
                success = generator.generate_for_project(
                    project=next(iter(generator.solution.projects.values())),
                    project_dir=project_dir,
                    debug=True,
                )
                assert success is True

                # Check for timing information
                # Get ALL logs to capture the complete build summary
                all_logs = log_capture

                # Look for the complete build summary section
                summary_start_index = None
                for i, log in enumerate(all_logs):
                    if "DEBUG MODE - Build Summary" in log:
                        summary_start_index = i
                        break

                assert summary_start_index is not None, "Build summary section not found in logs"

                summary_logs = []
                for i in range(summary_start_index, len(all_logs)):
                    log = all_logs[i]
                    summary_logs.append(log)

                    # Stop conditions:
                    # 1. Hit a new DEBUG MODE section that's not part of build summary
                    # 2. Hit a log separator (==================================================)
                    if i > summary_start_index:
                        if ("DEBUG MODE -" in log and "Build Summary" not in log) or (
                            "==================================================" in log
                        ):
                            break

                summary_text = " ".join(summary_logs)
                assert "Compilation time" in summary_text
                assert "Build completed at" in summary_text

                # Verify timing information is present
                assert "seconds" in summary_text or "time" in summary_text.lower()

            finally:
                logger.removeHandler(handler)
                logger.setLevel(original_level)


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