"""Tests for the PodmanCLI engine (OSS container engine)."""

import os
import shutil
import sys
import uuid
from pathlib import Path
from unittest import mock

import pytest

from fuzzforge_common.exceptions import FuzzForgeError
from fuzzforge_common.sandboxes.engines.podman.cli import PodmanCLI, _is_running_under_snap


# Helper to mock Linux platform for testing (since Podman is Linux-only)
def _mock_linux_platform() -> mock._patch[str]:
    """Context manager to mock sys.platform as 'linux'."""
    return mock.patch.object(sys, "platform", "linux")


@pytest.fixture
def podman_cli_engine() -> PodmanCLI:
    """Create a PodmanCLI engine with temporary storage.

    Uses short paths in /tmp to avoid podman's 50-char runroot limit.
    Simulates Snap environment to test custom storage paths.
    Mocks Linux platform since Podman is Linux-only.
    """
    short_id = str(uuid.uuid4())[:8]
    graphroot = Path(f"/tmp/ff-{short_id}/storage")
    runroot = Path(f"/tmp/ff-{short_id}/run")

    # Simulate Snap environment for testing on Linux
    with _mock_linux_platform(), mock.patch.dict(os.environ, {"SNAP": "/snap/code/123"}):
        engine = PodmanCLI(graphroot=graphroot, runroot=runroot)

    yield engine

    # Cleanup
    parent = graphroot.parent
    if parent.exists():
        shutil.rmtree(parent, ignore_errors=True)


def test_snap_detection_when_snap_set() -> None:
    """Test that SNAP environment is detected."""
    with mock.patch.dict(os.environ, {"SNAP": "/snap/code/123"}):
        assert _is_running_under_snap() is True


def test_snap_detection_when_snap_not_set() -> None:
    """Test that non-Snap environment is detected."""
    env = os.environ.copy()
    env.pop("SNAP", None)
    with mock.patch.dict(os.environ, env, clear=True):
        assert _is_running_under_snap() is False


def test_podman_cli_blocks_macos() -> None:
    """Test that PodmanCLI raises error on macOS."""
    with mock.patch.object(sys, "platform", "darwin"):
        with pytest.raises(FuzzForgeError) as exc_info:
            PodmanCLI()
        assert "Podman is not supported on macOS" in str(exc_info.value)
        assert "Docker" in str(exc_info.value)


def test_podman_cli_creates_storage_directories_under_snap() -> None:
    """Test that PodmanCLI creates storage directories when under Snap."""
    short_id = str(uuid.uuid4())[:8]
    graphroot = Path(f"/tmp/ff-{short_id}/storage")
    runroot = Path(f"/tmp/ff-{short_id}/run")

    assert not graphroot.exists()
    assert not runroot.exists()

    with _mock_linux_platform(), mock.patch.dict(os.environ, {"SNAP": "/snap/code/123"}):
        PodmanCLI(graphroot=graphroot, runroot=runroot)

    assert graphroot.exists()
    assert runroot.exists()

    # Cleanup
    shutil.rmtree(graphroot.parent, ignore_errors=True)


def test_podman_cli_base_cmd_under_snap() -> None:
    """Test that base command includes --root/--runroot under Snap."""
    short_id = str(uuid.uuid4())[:8]
    graphroot = Path(f"/tmp/ff-{short_id}/storage")
    runroot = Path(f"/tmp/ff-{short_id}/run")

    with _mock_linux_platform(), mock.patch.dict(os.environ, {"SNAP": "/snap/code/123"}):
        engine = PodmanCLI(graphroot=graphroot, runroot=runroot)
        base_cmd = engine._base_cmd()

    assert "podman" in base_cmd
    assert "--root" in base_cmd
    assert "--runroot" in base_cmd

    # Cleanup
    shutil.rmtree(graphroot.parent, ignore_errors=True)


def test_podman_cli_base_cmd_without_snap() -> None:
    """Test that base command is plain 'podman' when not under Snap."""
    short_id = str(uuid.uuid4())[:8]
    graphroot = Path(f"/tmp/ff-{short_id}/storage")
    runroot = Path(f"/tmp/ff-{short_id}/run")

    env = os.environ.copy()
    env.pop("SNAP", None)
    with _mock_linux_platform(), mock.patch.dict(os.environ, env, clear=True):
        engine = PodmanCLI(graphroot=graphroot, runroot=runroot)
        base_cmd = engine._base_cmd()

    assert base_cmd == ["podman"]
    assert "--root" not in base_cmd

    # Directories should NOT be created when not under Snap
    assert not graphroot.exists()


def test_podman_cli_default_mode() -> None:
    """Test PodmanCLI without custom storage paths."""
    with _mock_linux_platform():
        engine = PodmanCLI()  # No paths provided
        base_cmd = engine._base_cmd()

    assert base_cmd == ["podman"]
    assert "--root" not in base_cmd


def test_podman_cli_list_images_returns_list(podman_cli_engine: PodmanCLI) -> None:
    """Test that list_images returns a list (even if empty)."""
    images = podman_cli_engine.list_images()

    assert isinstance(images, list)


@pytest.mark.skip(reason="Requires pulling images, slow integration test")
def test_podman_cli_can_pull_and_list_image(podman_cli_engine: PodmanCLI) -> None:
    """Test pulling an image and listing it."""
    # Pull a small image
    podman_cli_engine._run(["pull", "docker.io/library/alpine:latest"])

    images = podman_cli_engine.list_images()
    assert any("alpine" in img.identifier for img in images)
