"""Pytest configuration and shared fixtures."""

from __future__ import annotations

import logging
import os
import sys
from pathlib import Path
from unittest.mock import MagicMock

import pytest

# Add src directory to path for imports
sys.path.insert(0, str(Path(__file__).parent.parent / "src"))


@pytest.fixture
def temp_dir(tmp_path: Path) -> Path:
    """Create a temporary directory for testing.

    Args:
        tmp_path: Pytest's built-in tmp_path fixture.

    Returns:
        Path to temporary directory.
    """
    return tmp_path


@pytest.fixture
def sandbox_dir() -> Path:
    """Get path to the test sandbox directory.

    Returns:
        Path to sandbox directory.
    """
    return Path(__file__).parent / "sandbox"


@pytest.fixture
def fake_apps_dir(sandbox_dir: Path) -> Path:
    """Get path to fake apps directory.

    Args:
        sandbox_dir: Path to sandbox directory.

    Returns:
        Path to fake apps directory.
    """
    return sandbox_dir / "fake_apps"


@pytest.fixture
def mock_platform_darwin(monkeypatch: pytest.MonkeyPatch) -> None:
    """Mock platform as macOS (darwin).

    Args:
        monkeypatch: Pytest's monkeypatch fixture.
    """
    monkeypatch.setattr(sys, "platform", "darwin")


@pytest.fixture
def mock_platform_linux(monkeypatch: pytest.MonkeyPatch) -> None:
    """Mock platform as Linux.

    Args:
        monkeypatch: Pytest's monkeypatch fixture.
    """
    monkeypatch.setattr(sys, "platform", "linux")


@pytest.fixture
def mock_is_root(monkeypatch: pytest.MonkeyPatch) -> None:
    """Mock os.geteuid to return 0 (root).

    Args:
        monkeypatch: Pytest's monkeypatch fixture.
    """
    monkeypatch.setattr(os, "geteuid", lambda: 0)


@pytest.fixture
def mock_is_not_root(monkeypatch: pytest.MonkeyPatch) -> None:
    """Mock os.geteuid to return non-zero (not root).

    Args:
        monkeypatch: Pytest's monkeypatch fixture.
    """
    monkeypatch.setattr(os, "geteuid", lambda: 1000)


@pytest.fixture
def mock_subprocess_run_success(monkeypatch: pytest.MonkeyPatch) -> MagicMock:
    """Mock subprocess.run to always succeed.

    Args:
        monkeypatch: Pytest's monkeypatch fixture.

    Returns:
        MagicMock instance.
    """
    mock = MagicMock()
    mock.returncode = 0
    mock.stdout = ""
    mock.stderr = ""

    def run_mock(*args, **kwargs):
        return mock

    monkeypatch.setattr("subprocess.run", run_mock)
    return mock


@pytest.fixture
def mock_subprocess_run_failure(monkeypatch: pytest.MonkeyPatch) -> MagicMock:
    """Mock subprocess.run to always fail.

    Args:
        monkeypatch: Pytest's monkeypatch fixture.

    Returns:
        MagicMock instance.
    """
    mock = MagicMock()
    mock.returncode = 1
    mock.stdout = ""
    mock.stderr = "Error"

    def run_mock(*args, **kwargs):
        return mock

    monkeypatch.setattr("subprocess.run", run_mock)
    return mock


@pytest.fixture
def mock_logger(caplog: pytest.LogCaptureFixture) -> logging.Logger:
    """Get a logger instance with capture enabled.

    Args:
        caplog: Pytest's caplog fixture.

    Returns:
        Logger instance.
    """
    logger = logging.getLogger("electron_angle_patcher")
    logger.setLevel(logging.DEBUG)

    with caplog.at_level(logging.DEBUG):
        yield logger

    return logger


@pytest.fixture
def sample_local_state() -> dict:
    """Sample Local State JSON data.

    Returns:
        Dictionary with sample Local State data.
    """
    return {
        "browser": {
            "enabled_labs_experiments": [
                "some-feature@2",
                "another-feature@1",
            ]
        }
    }


@pytest.fixture
def sample_local_state_with_angle() -> dict:
    """Sample Local State JSON data with use-angle already set.

    Returns:
        Dictionary with sample Local State data including use-angle.
    """
    return {
        "browser": {
            "enabled_labs_experiments": [
                "some-feature@2",
                "use-angle@1",
                "another-feature@1",
            ]
        }
    }


@pytest.fixture
def sample_local_state_empty() -> dict:
    """Empty Local State JSON data.

    Returns:
        Empty dictionary.
    """
    return {}


@pytest.fixture
def mock_local_state_file(temp_dir: Path, sample_local_state: dict) -> Path:
    """Create a mock Local State file.

    Args:
        temp_dir: Temporary directory fixture.
        sample_local_state: Sample data fixture.

    Returns:
        Path to the created file.
    """
    import json

    local_state_path = temp_dir / "Local State"
    local_state_path.write_text(json.dumps(sample_local_state))
    return local_state_path


@pytest.fixture
def mock_app_bundle(temp_dir: Path) -> Path:
    """Create a mock macOS app bundle structure.

    Args:
        temp_dir: Temporary directory fixture.

    Returns:
        Path to the mock app bundle.
    """
    app_path = temp_dir / "TestApp.app"
    macos_path = app_path / "Contents" / "MacOS"
    macos_path.mkdir(parents=True)

    # Create a fake executable
    executable = macos_path / "TestApp"
    executable.write_text("#!/bin/bash\necho 'fake app'\n")
    executable.chmod(0o755)

    return app_path
