"""Common fixtures for the portainer tests."""

from collections.abc import Generator
from unittest.mock import AsyncMock, patch

from pyportainer.models.docker import (
    DockerContainer,
    DockerContainerStats,
    DockerSystemDF,
    DockerVolume,
)
from pyportainer.models.docker_inspect import DockerInfo, DockerVersion
from pyportainer.models.portainer import Endpoint, PortainerSystemStatus
from pyportainer.models.stacks import Stack
import pytest

from homeassistant.components.portainer.const import DOMAIN
from homeassistant.const import CONF_API_TOKEN, CONF_URL, CONF_VERIFY_SSL

from tests.common import (
    MockConfigEntry,
    load_json_array_fixture,
    load_json_value_fixture,
)

MOCK_TEST_CONFIG = {
    CONF_URL: "https://127.0.0.1:9000/",
    CONF_API_TOKEN: "test_api_token",
    CONF_VERIFY_SSL: True,
}

TEST_ENTRY = "portainer_test_entry_123"
TEST_INSTANCE_ID = "299ab403-70a8-4c05-92f7-bf7a994d50df"


@pytest.fixture
def mock_setup_entry() -> Generator[AsyncMock]:
    """Override async_setup_entry."""
    with patch(
        "homeassistant.components.portainer.async_setup_entry", return_value=True
    ) as mock_setup_entry:
        yield mock_setup_entry


@pytest.fixture
def mock_portainer_client() -> Generator[AsyncMock]:
    """Mock Portainer client with dynamic exception injection support."""
    with (
        patch(
            "homeassistant.components.portainer.Portainer", autospec=True
        ) as mock_client,
        patch(
            "homeassistant.components.portainer.config_flow.Portainer", new=mock_client
        ),
    ):
        client = mock_client.return_value

        client.get_endpoints.return_value = [
            Endpoint.from_dict(endpoint)
            for endpoint in load_json_array_fixture("endpoints.json", DOMAIN)
        ]
        client.get_containers.return_value = [
            DockerContainer.from_dict(container)
            for container in load_json_array_fixture("containers.json", DOMAIN)
        ]
        client.docker_info.return_value = DockerInfo.from_dict(
            load_json_value_fixture("docker_info.json", DOMAIN)
        )
        client.docker_version.return_value = DockerVersion.from_dict(
            load_json_value_fixture("docker_version.json", DOMAIN)
        )
        client.container_stats.return_value = DockerContainerStats.from_dict(
            load_json_value_fixture("container_stats.json", DOMAIN)
        )
        client.docker_system_df.return_value = DockerSystemDF.from_dict(
            load_json_value_fixture("docker_system_df.json", DOMAIN)
        )
        client.get_stacks.return_value = [
            Stack.from_dict(stack)
            for stack in load_json_array_fixture("stacks.json", DOMAIN)
        ]
        client.portainer_system_status.return_value = PortainerSystemStatus.from_dict(
            load_json_value_fixture("portainer_system_status.json", DOMAIN)
        )
        client.get_volumes.return_value = [
            DockerVolume.from_dict(volume)
            for volume in load_json_array_fixture("volumes.json", DOMAIN)
        ]

        client.restart_container = AsyncMock(return_value=None)
        client.images_prune = AsyncMock(return_value=None)
        client.start_container = AsyncMock(return_value=None)
        client.stop_container = AsyncMock(return_value=None)
        client.start_stack = AsyncMock(return_value=None)
        client.stop_stack = AsyncMock(return_value=None)

        yield client


@pytest.fixture
def mock_config_entry() -> MockConfigEntry:
    """Mock a config entry."""
    return MockConfigEntry(
        domain=DOMAIN,
        title="Portainer test",
        data=MOCK_TEST_CONFIG,
        unique_id=TEST_INSTANCE_ID,
        entry_id=TEST_ENTRY,
        version=5,
    )
