"""
Shared fixtures. A non-interactive backend is selected before pyplot is imported
anywhere, so the suite runs headless in CI.
"""

import matplotlib
matplotlib.use("Agg")

import numpy as np
import pandas as pd
import pytest
import matplotlib.pyplot as plt


@pytest.fixture(autouse=True)
def close_figures():
    """Keep matplotlib from accumulating open figures across tests."""
    yield
    plt.close("all")


@pytest.fixture
def rng():
    return np.random.default_rng(42)


@pytest.fixture
def df(rng):
    """Small mixed categorical/continuous frame covering the common call shapes."""
    n = 60
    return pd.DataFrame({
        "x": rng.normal(size=n),
        "y": rng.normal(size=n),
        "value": rng.uniform(1, 10, size=n),
        "cat": pd.Categorical(rng.choice(["a", "b", "c"], size=n)),
        "group": pd.Categorical(rng.choice(["g1", "g2"], size=n)),
        "cont": rng.uniform(size=n),
    })


@pytest.fixture
def df_matrix(rng):
    """Numeric frame for heatmap-style functions."""
    return pd.DataFrame(
        rng.normal(size=(8, 6)),
        index=[f"row{i}" for i in range(8)],
        columns=[f"col{j}" for j in range(6)],
    )


@pytest.fixture
def df_volcano(rng):
    n = 100
    return pd.DataFrame({
        "log2FC": rng.normal(scale=1.5, size=n),
        "-log10p": rng.uniform(0, 6, size=n),
    }, index=[f"gene{i}" for i in range(n)])


@pytest.fixture
def ax():
    fig, ax = plt.subplots(figsize=(4, 4))
    return ax
