"""Tests for parallel tree fitting."""
import time

import numpy as np
import pytest
from sklearn.datasets import make_classification

from georf import GeoRFClassifier


def _dataset(n=200, seed=0):
    return make_classification(
        n_samples=n, n_features=5, n_informative=3, random_state=seed
    )


# ── 1. n_jobs=1 and n_jobs=2 produce identical predictions ───────────────────

def test_deterministic_njobs1_vs_njobs2():
    X, y = _dataset(n=100)
    kwargs = dict(n_estimators=10, n_samples_per_tree=150, random_state=42)

    clf1 = GeoRFClassifier(**kwargs, n_jobs=1)
    clf1.fit(X, y)

    clf2 = GeoRFClassifier(**kwargs, n_jobs=2)
    clf2.fit(X, y)

    preds1 = clf1.predict(X)
    preds2 = clf2.predict(X)
    np.testing.assert_array_equal(
        preds1, preds2,
        err_msg="n_jobs=1 and n_jobs=2 should produce identical predictions",
    )


# ── 2. n_jobs=-1 runs without error ──────────────────────────────────────────

def test_njobs_all_cores():
    X, y = _dataset(n=100)
    clf = GeoRFClassifier(n_estimators=5, n_samples_per_tree=100,
                          random_state=0, n_jobs=-1)
    clf.fit(X, y)
    clf.predict(X[:10])


# ── 3. n_jobs=2 is faster than n_jobs=1 (timing, 30% tolerance) ─────────────

@pytest.mark.slow
def test_parallel_speedup():
    """n_jobs=2 should be meaningfully faster than n_jobs=1 on a larger ensemble."""
    X, y = _dataset(n=200)
    kwargs = dict(n_estimators=100, n_samples_per_tree=500, random_state=7)

    t0 = time.perf_counter()
    GeoRFClassifier(**kwargs, n_jobs=1).fit(X, y)
    t_single = time.perf_counter() - t0

    t0 = time.perf_counter()
    GeoRFClassifier(**kwargs, n_jobs=2).fit(X, y)
    t_parallel = time.perf_counter() - t0

    # Allow 30% tolerance: parallel should not be slower than 0.7× single
    assert t_parallel <= t_single * 0.70 + 1.0, (
        f"Parallel ({t_parallel:.2f}s) not faster than single ({t_single:.2f}s) "
        "within 30% tolerance"
    )
