"""Test suite for enhanced pypack dependency detection and error handling."""

from pathlib import Path
from unittest import mock

from ..core.config import WorkflowConfig
from ..core.workflow import PackageWorkflow, StandardCleaningStrategy


class TestEnhancedDependencyDetection:
    """Test enhanced dependency detection and pre-execution checks."""

    def test_pre_execution_checks_success(self, tmp_path: Path):
        """Test successful pre-execution checks."""
        # Setup test environment
        dist_dir = tmp_path / "dist"
        dist_dir.mkdir()

        # Create executable file
        exe_file = dist_dir / "test_app.exe"
        exe_file.touch()
        exe_file.chmod(0o755)  # Make executable

        # Create runtime directory with Python interpreter
        runtime_dir = dist_dir / "runtime"
        runtime_dir.mkdir()
        python_exe = runtime_dir / "python.exe"  # Always use Windows path for test
        python_exe.touch()
        python_exe.chmod(0o755)

        # Create site-packages with some packages
        site_packages = dist_dir / "site-packages"
        site_packages.mkdir()
        (site_packages / "requests").mkdir()
        (site_packages / "numpy").mkdir()

        # Setup workflow
        config = WorkflowConfig(directory=tmp_path)
        workflow = PackageWorkflow(
            root_dir=tmp_path,
            config=config,
            cleaning_strategy=StandardCleaningStrategy(),
        )

        # Execute the method - should return True for successful checks
        result = workflow._pre_execution_checks(exe_file)
        assert result is True

    def test_pre_execution_checks_missing_executable(self, tmp_path: Path):
        """Test pre-execution checks with missing executable."""
        dist_dir = tmp_path / "dist"
        dist_dir.mkdir()

        config = WorkflowConfig(directory=tmp_path)
        workflow = PackageWorkflow(
            root_dir=tmp_path,
            config=config,
            cleaning_strategy=StandardCleaningStrategy(),
        )

        missing_exe = dist_dir / "missing_app.exe"

        # Should return False for missing executable
        result = workflow._pre_execution_checks(missing_exe)
        assert result is False

    def test_pre_execution_checks_missing_runtime(self, tmp_path: Path):
        """Test pre-execution checks with missing runtime."""
        dist_dir = tmp_path / "dist"
        dist_dir.mkdir()

        # Create executable but no runtime
        exe_file = dist_dir / "test_app.exe"
        exe_file.touch()
        exe_file.chmod(0o755)

        config = WorkflowConfig(directory=tmp_path)
        workflow = PackageWorkflow(
            root_dir=tmp_path,
            config=config,
            cleaning_strategy=StandardCleaningStrategy(),
        )

        # Should return False for missing runtime
        result = workflow._pre_execution_checks(exe_file)
        assert result is False

    def test_is_gui_application_detection(self, tmp_path: Path):
        """Test GUI application detection."""
        config = WorkflowConfig(directory=tmp_path)
        workflow = PackageWorkflow(
            root_dir=tmp_path,
            config=config,
            cleaning_strategy=StandardCleaningStrategy(),
        )

        # Test GUI-like names
        assert workflow._is_gui_application(Path("app_gui.exe")) is True
        assert workflow._is_gui_application(Path("myapp-interface")) is True
        assert workflow._is_gui_application(Path("window_manager.py")) is True

        # Test non-GUI names
        assert workflow._is_gui_application(Path("cli_tool.exe")) is False
        assert workflow._is_gui_application(Path("background_service")) is False

    def test_check_gui_dependencies_with_pyside2(self, tmp_path: Path):
        """Test GUI dependency checking with PySide2."""
        dist_dir = tmp_path / "dist"
        dist_dir.mkdir()

        # Create site-packages with PySide2
        site_packages = dist_dir / "site-packages"
        site_packages.mkdir()
        pyside2_dir = site_packages / "PySide2"
        pyside2_dir.mkdir()

        config = WorkflowConfig(directory=tmp_path)
        workflow = PackageWorkflow(
            root_dir=tmp_path,
            config=config,
            cleaning_strategy=StandardCleaningStrategy(),
        )

        # Should return True when PySide2 is found
        result = workflow._check_gui_dependencies()
        assert result is True

    def test_check_gui_dependencies_none_found(self, tmp_path: Path):
        """Test GUI dependency checking when no frameworks found."""
        dist_dir = tmp_path / "dist"
        dist_dir.mkdir()

        # Create empty site-packages
        site_packages = dist_dir / "site-packages"
        site_packages.mkdir()

        config = WorkflowConfig(directory=tmp_path)
        workflow = PackageWorkflow(
            root_dir=tmp_path,
            config=config,
            cleaning_strategy=StandardCleaningStrategy(),
        )

        # Should return False when no GUI frameworks found
        result = workflow._check_gui_dependencies()
        assert result is False

    def test_run_project_with_enhanced_checks(self, tmp_path: Path):
        """Test run_project with enhanced pre-execution checks."""
        dist_dir = tmp_path / "dist"
        dist_dir.mkdir()

        # Create a mock executable
        exe_file = dist_dir / "test_app.exe"
        exe_file.touch()

        config = WorkflowConfig(directory=tmp_path)

        # Create a test subclass that allows mocking
        class TestablePackageWorkflow(PackageWorkflow):
            def _pre_execution_checks(self, exe_path):
                return False  # Always fail for testing

        workflow = TestablePackageWorkflow(
            root_dir=tmp_path,
            config=config,
            cleaning_strategy=StandardCleaningStrategy(),
        )

        # Mock subprocess to avoid actual execution
        with mock.patch("subprocess.run") as mock_run:
            mock_run.return_value = mock.Mock(returncode=0, stdout="", stderr="")

            # This should not call subprocess since pre-checks fail
            workflow.run_project("test_app")

            # Verify subprocess was not called
            mock_run.assert_not_called()

    def test_run_project_successful_execution(self, tmp_path: Path):
        """Test successful project execution with enhanced checks."""
        dist_dir = tmp_path / "dist"
        dist_dir.mkdir()

        # Setup complete environment
        exe_file = dist_dir / "test_app.exe"
        exe_file.touch()
        exe_file.chmod(0o755)

        runtime_dir = dist_dir / "runtime"
        runtime_dir.mkdir()
        python_exe = runtime_dir / "python.exe"
        python_exe.touch()
        python_exe.chmod(0o755)

        config = WorkflowConfig(directory=tmp_path)

        # Create a test subclass that allows mocking
        class TestablePackageWorkflow(PackageWorkflow):
            def _pre_execution_checks(self, exe_path):
                return True  # Always succeed for testing

        workflow = TestablePackageWorkflow(
            root_dir=tmp_path,
            config=config,
            cleaning_strategy=StandardCleaningStrategy(),
        )

        with mock.patch("subprocess.run") as mock_run:
            mock_result = mock.Mock(returncode=0, stdout="Success!", stderr="")
            mock_run.return_value = mock_result

            # Should execute successfully
            workflow.run_project("test_app")

            # Verify subprocess was called
            mock_run.assert_called_once()
