"""Tests para call_batch_with_retry."""

import sys
import os

sys.path.insert(0, os.path.dirname(__file__))

from call_batch_with_retry import call_batch_with_retry


def test_todos_los_items_exito():
    results, failures = call_batch_with_retry(
        items=[1, 2, 3],
        process_func=lambda x: x * 2,
        max_retries=3,
    )
    assert results == [2, 4, 6]
    assert failures == []


def test_item_falla_permanentemente_continue_true():
    def process(x):
        if x == 2:
            raise ValueError("fallo permanente")
        return x * 10

    results, failures = call_batch_with_retry(
        items=[1, 2, 3],
        process_func=process,
        max_retries=2,
        initial_delay=0.0,
        continue_on_failure=True,
    )
    assert results == [10, 30]
    assert len(failures) == 1
    assert failures[0]["index"] == 1
    assert failures[0]["item"] == 2
    assert "fallo permanente" in failures[0]["error"]


def test_item_falla_abort_continue_false():
    call_count = {"n": 0}

    def process(x):
        call_count["n"] += 1
        if x == 2:
            raise RuntimeError("error fatal")
        return x

    try:
        call_batch_with_retry(
            items=[1, 2, 3],
            process_func=process,
            max_retries=1,
            initial_delay=0.0,
            continue_on_failure=False,
        )
        assert False, "Deberia haber lanzado excepcion"
    except RuntimeError as e:
        assert "error fatal" in str(e)
    # item 3 nunca fue procesado
    assert call_count["n"] < 6  # 1 ok + 2 intentos para item 2 + 0 para item 3


def test_item_falla_luego_exito_retry_funciona():
    attempt_counts = {}

    def process(x):
        attempt_counts[x] = attempt_counts.get(x, 0) + 1
        # item 5 falla las primeras 2 veces, exito en la tercera
        if x == 5 and attempt_counts[x] < 3:
            raise ValueError("fallo temporal")
        return x * 2

    results, failures = call_batch_with_retry(
        items=[1, 5, 9],
        process_func=process,
        max_retries=3,
        initial_delay=0.0,
        continue_on_failure=True,
    )
    assert results == [2, 10, 18]
    assert failures == []
    assert attempt_counts[5] == 3


def test_failures_contiene_index_correcto():
    def process(x):
        if x in (0, 2, 4):
            raise ValueError(f"fallo en {x}")
        return x

    results, failures = call_batch_with_retry(
        items=[0, 1, 2, 3, 4],
        process_func=process,
        max_retries=0,
        initial_delay=0.0,
        continue_on_failure=True,
    )
    assert results == [1, 3]
    assert [f["index"] for f in failures] == [0, 2, 4]
    assert [f["item"] for f in failures] == [0, 2, 4]
