"""Shared test fixtures for BilgeAI."""

import json

import pytest

from bilgeai.analyzer.models import DatasetProfile
from bilgeai.profiler.models import GPUInfo, HardwareProfile

# --- GPU Fixtures ---


@pytest.fixture
def gpu_4gb():
    return GPUInfo(
        name="NVIDIA GTX 1650",
        vram_gb=4.0,
        cuda_version="12.1",
        compute_capability="7.5",
    )


@pytest.fixture
def gpu_8gb():
    return GPUInfo(
        name="NVIDIA RTX 3070",
        vram_gb=8.0,
        cuda_version="12.1",
        compute_capability="8.6",
    )


@pytest.fixture
def gpu_24gb():
    return GPUInfo(
        name="NVIDIA RTX 4090",
        vram_gb=24.0,
        cuda_version="12.4",
        compute_capability="8.9",
    )


@pytest.fixture
def gpu_80gb():
    return GPUInfo(name="NVIDIA A100", vram_gb=80.0, cuda_version="12.4", compute_capability="8.0")


# --- Hardware Profile Fixtures ---


@pytest.fixture
def hw_no_gpu():
    return HardwareProfile(
        cpu_cores=4,
        cpu_name="Intel i5",
        ram_total_gb=16.0,
        ram_available_gb=12.0,
        disk_free_gb=50.0,
        gpus=[],
        os="Linux",
        python_version="3.11.0",
        torch_version=None,
        cuda_available=False,
    )


@pytest.fixture
def hw_low_gpu(gpu_4gb):
    return HardwareProfile(
        cpu_cores=8,
        cpu_name="AMD Ryzen 5",
        ram_total_gb=16.0,
        ram_available_gb=12.0,
        disk_free_gb=80.0,
        gpus=[gpu_4gb],
        os="Linux",
        python_version="3.11.0",
        torch_version="2.2.0",
        cuda_available=True,
    )


@pytest.fixture
def hw_mid_gpu(gpu_8gb):
    return HardwareProfile(
        cpu_cores=8,
        cpu_name="AMD Ryzen 7 5800X",
        ram_total_gb=32.0,
        ram_available_gb=24.0,
        disk_free_gb=100.0,
        gpus=[gpu_8gb],
        os="Linux",
        python_version="3.11.0",
        torch_version="2.2.0",
        cuda_available=True,
    )


@pytest.fixture
def hw_high_gpu(gpu_24gb):
    return HardwareProfile(
        cpu_cores=16,
        cpu_name="AMD Ryzen 9",
        ram_total_gb=64.0,
        ram_available_gb=48.0,
        disk_free_gb=500.0,
        gpus=[gpu_24gb],
        os="Linux",
        python_version="3.11.0",
        torch_version="2.2.0",
        cuda_available=True,
    )


@pytest.fixture
def hw_multi_gpu(gpu_8gb):
    return HardwareProfile(
        cpu_cores=32,
        cpu_name="AMD EPYC 7543",
        ram_total_gb=256.0,
        ram_available_gb=200.0,
        disk_free_gb=1000.0,
        gpus=[gpu_8gb, gpu_8gb],
        os="Linux",
        python_version="3.11.0",
        torch_version="2.2.0",
        cuda_available=True,
    )


@pytest.fixture
def hw_4x_low_gpu(gpu_4gb):
    """4 GPUs with low VRAM each - triggers DeepSpeed."""
    return HardwareProfile(
        cpu_cores=64,
        cpu_name="AMD EPYC 7543",
        ram_total_gb=256.0,
        ram_available_gb=200.0,
        disk_free_gb=1000.0,
        gpus=[gpu_4gb, gpu_4gb, gpu_4gb, gpu_4gb],
        os="Linux",
        python_version="3.11.0",
        torch_version="2.2.0",
        cuda_available=True,
    )


@pytest.fixture
def hw_8x_a100():
    gpus = [
        GPUInfo(name="NVIDIA A100", vram_gb=80.0, cuda_version="12.4", compute_capability="8.0")
        for _ in range(8)
    ]
    return HardwareProfile(
        cpu_cores=128,
        cpu_name="AMD EPYC 7763",
        ram_total_gb=1024.0,
        ram_available_gb=900.0,
        disk_free_gb=5000.0,
        gpus=gpus,
        os="Linux",
        python_version="3.11.0",
        torch_version="2.2.0",
        cuda_available=True,
    )


# --- Dataset Fixtures ---


@pytest.fixture
def small_dataset_profile():
    return DatasetProfile(
        path="./test.jsonl",
        format="alpaca",
        num_rows=500,
        num_columns=3,
        columns=["instruction", "input", "output"],
        avg_tokens=150.0,
        min_tokens=20,
        max_tokens=800,
        p50_tokens=120,
        p90_tokens=300,
        p99_tokens=600,
        estimated_size_mb=0.5,
    )


@pytest.fixture
def medium_dataset_profile():
    return DatasetProfile(
        path="./test.jsonl",
        format="alpaca",
        num_rows=5000,
        num_columns=3,
        columns=["instruction", "input", "output"],
        avg_tokens=250.0,
        min_tokens=10,
        max_tokens=2000,
        p50_tokens=200,
        p90_tokens=500,
        p99_tokens=1500,
        estimated_size_mb=5.0,
    )


@pytest.fixture
def large_dataset_profile():
    return DatasetProfile(
        path="./test.jsonl",
        format="sharegpt",
        num_rows=150000,
        num_columns=1,
        columns=["conversations"],
        avg_tokens=300.0,
        min_tokens=50,
        max_tokens=4000,
        p50_tokens=250,
        p90_tokens=600,
        p99_tokens=3000,
        estimated_size_mb=200.0,
    )


# --- Sample Data Files ---


@pytest.fixture
def sample_alpaca_jsonl(tmp_path):
    data = [
        {
            "instruction": "What is Python?",
            "input": "",
            "output": "Python is a programming language.",
        },
        {
            "instruction": "Explain OOP.",
            "input": "",
            "output": "OOP stands for Object-Oriented Programming.",
        },
        {
            "instruction": "What is a list?",
            "input": "",
            "output": "A list is an ordered collection.",
        },
    ]
    path = tmp_path / "train.jsonl"
    path.write_text("\n".join(json.dumps(d, ensure_ascii=False) for d in data), encoding="utf-8")
    return path


@pytest.fixture
def sample_sharegpt_jsonl(tmp_path):
    data = [
        {
            "conversations": [
                {"from": "human", "value": "Hello"},
                {"from": "gpt", "value": "Hi there!"},
            ]
        },
    ]
    path = tmp_path / "train.jsonl"
    path.write_text("\n".join(json.dumps(d) for d in data), encoding="utf-8")
    return path


@pytest.fixture
def sample_config_yaml(tmp_path):
    """Legacy config for testing auto-migration."""
    content = """schema_version: "0.0.1"
model:
  name: "meta-llama/Llama-3-8B"
data:
  path: "./train.jsonl"
  format: auto
training: {}
llm:
  ollama: false
  remote: false
privacy:
  scan_pii: true
"""
    path = tmp_path / "bilge.yaml"
    path.write_text(content, encoding="utf-8")
    return path


@pytest.fixture
def sample_config_yaml_v2(tmp_path):
    """Current v0.1.0 config with provider-based LLM settings."""
    content = """schema_version: "0.1.0"
model:
  name: "meta-llama/Llama-3-8B"
data:
  path: "./train.jsonl"
  format: auto
training: {}
llm:
  provider: "anthropic"
  model: "claude-sonnet-4-20250514"
  api_key_env: "ANTHROPIC_API_KEY"
privacy:
  scan_pii: true
"""
    path = tmp_path / "bilge.yaml"
    path.write_text(content, encoding="utf-8")
    return path


@pytest.fixture
def cli_runner():
    from typer.testing import CliRunner

    return CliRunner()
