"""Root conftest - shared fixtures and step definitions for all VIP tests."""

from __future__ import annotations

import pytest
from pytest_bdd import given

from vip.clients.connect import ConnectClient
from vip.clients.packagemanager import PackageManagerClient
from vip.clients.workbench import WorkbenchClient
from vip.config import PerformanceConfig, VIPConfig
from vip.plugin import _auth_session_key, _vip_config_key

# ---------------------------------------------------------------------------
# Configuration fixture
# ---------------------------------------------------------------------------


@pytest.fixture(scope="session")
def vip_config(request: pytest.FixtureRequest) -> VIPConfig:
    """The loaded VIP configuration for this test run."""
    return request.config.stash[_vip_config_key]


# ---------------------------------------------------------------------------
# Product client fixtures
# ---------------------------------------------------------------------------


@pytest.fixture(scope="session")
def connect_client(vip_config: VIPConfig) -> ConnectClient | None:
    if not vip_config.connect.is_configured:
        return None
    client = ConnectClient(vip_config.connect.url, api_key=vip_config.connect.api_key)
    yield client
    client.close()


@pytest.fixture(scope="session")
def connect_url(vip_config: VIPConfig) -> str:
    return vip_config.connect.url


@pytest.fixture(scope="session")
def workbench_client(vip_config: VIPConfig) -> WorkbenchClient | None:
    if not vip_config.workbench.is_configured:
        return None
    client = WorkbenchClient(vip_config.workbench.url, api_key=vip_config.workbench.api_key)
    yield client
    client.close()


@pytest.fixture(scope="session")
def workbench_url(vip_config: VIPConfig) -> str:
    return vip_config.workbench.url


@pytest.fixture(scope="session")
def pm_client(vip_config: VIPConfig) -> PackageManagerClient | None:
    if not vip_config.package_manager.is_configured:
        return None
    client = PackageManagerClient(
        vip_config.package_manager.url, token=vip_config.package_manager.token
    )
    yield client
    client.close()


@pytest.fixture(scope="session")
def pm_url(vip_config: VIPConfig) -> str:
    return vip_config.package_manager.url


# ---------------------------------------------------------------------------
# Auth fixtures
# ---------------------------------------------------------------------------


@pytest.fixture(scope="session")
def interactive_auth(request: pytest.FixtureRequest) -> bool:
    """Whether interactive auth was used for this session."""
    session = request.config.stash.get(_auth_session_key, None)
    return session is not None


@pytest.fixture(scope="session")
def browser_context_args(browser_context_args, request: pytest.FixtureRequest):
    """Inject interactive auth storage state into all browser contexts.

    Overrides the pytest-playwright fixture of the same name.  The parameter
    name *must* match to receive the base fixture value.
    """
    session = request.config.stash.get(_auth_session_key, None)
    if session is not None:
        browser_context_args["storage_state"] = str(session.storage_state_path)
    return browser_context_args


@pytest.fixture(scope="session")
def test_username(vip_config: VIPConfig) -> str:
    return vip_config.auth.username


@pytest.fixture(scope="session")
def test_password(vip_config: VIPConfig) -> str:
    return vip_config.auth.password


@pytest.fixture(scope="session")
def auth_provider(vip_config: VIPConfig) -> str:
    return vip_config.auth.provider


# ---------------------------------------------------------------------------
# Runtime fixtures
# ---------------------------------------------------------------------------


@pytest.fixture(scope="session")
def expected_r_versions(vip_config: VIPConfig) -> list[str]:
    return vip_config.runtimes.r_versions


@pytest.fixture(scope="session")
def expected_python_versions(vip_config: VIPConfig) -> list[str]:
    return vip_config.runtimes.python_versions


# ---------------------------------------------------------------------------
# Performance fixtures
# ---------------------------------------------------------------------------


@pytest.fixture(scope="session")
def performance_config(vip_config: VIPConfig) -> PerformanceConfig:
    return vip_config.performance


# ---------------------------------------------------------------------------
# Data source fixtures
# ---------------------------------------------------------------------------


@pytest.fixture(scope="session")
def data_sources(vip_config: VIPConfig):
    return vip_config.data_sources


# ---------------------------------------------------------------------------
# Feature flags
# ---------------------------------------------------------------------------


@pytest.fixture(scope="session")
def email_enabled(vip_config: VIPConfig) -> bool:
    return vip_config.email_enabled


# ---------------------------------------------------------------------------
# Shared BDD steps — product configuration guards
# ---------------------------------------------------------------------------


@given("Connect is configured in vip.toml")
def connect_configured(vip_config):
    if not vip_config.connect.is_configured:
        pytest.skip("Connect is not configured")


@given("Workbench is configured in vip.toml")
def workbench_configured(vip_config):
    if not vip_config.workbench.is_configured:
        pytest.skip("Workbench is not configured")


@given("Package Manager is configured in vip.toml")
def package_manager_configured(vip_config):
    if not vip_config.package_manager.is_configured:
        pytest.skip("Package Manager is not configured")
