// Pruebas de Tally: casos dirigidos y operaciones al azar con semilla fija.
#include <algorithm>
#include <cassert>
#include <iostream>
#include <numeric>
#include <random>
#include <vector>

#include "tally.h"

void test_starts_empty() {
    Tally tally;
    assert(tally.count() == 0);
    assert(tally.sum() == 0);
}

void test_one_value() {
    Tally tally;
    tally.add(-3);
    assert(tally.count() == 1);
    assert(tally.sum() == -3);
    assert(tally.max() == -3);
}

void test_read_through_const_reference(const Tally& tally) {
    assert(tally.count() == 3);
    assert(tally.max() == 17);
}

void test_several_values() {
    Tally tally;
    tally.add(14);
    tally.add(9);
    tally.add(17);
    assert(tally.sum() == 40);
    test_read_through_const_reference(tally);
}

// Compara contra un std::vector, que hace de referencia.
void test_against_reference() {
    std::mt19937 random(2026);
    Tally tally;
    std::vector<int> reference;
    for (int step = 0; step < 2000; step++) {
        int value = static_cast<int>(random() % 201) - 100;
        tally.add(value);
        reference.push_back(value);
        assert(tally.count() == reference.size());
        assert(tally.sum() == std::accumulate(reference.begin(), reference.end(), 0));
        assert(tally.max() == *std::max_element(reference.begin(), reference.end()));
    }
}

int main() {
    test_starts_empty();
    test_one_value();
    test_several_values();
    test_against_reference();
    std::cout << "tally: todas las pruebas pasaron\n";
    return 0;
}
