/* tests.c -- rangkaian test untuk modul csv_reader dan parser. */

#include "csv_reader.h"
#include "parser.h"

#include <stdio.h>
#include <math.h>
#include <string.h>

static int lulus = 0;
static int gagal = 0;

#define PERIKSA(kondisi, nama)                              \
    do {                                                    \
        if (kondisi) { lulus++; printf("[LULUS] %s\n", nama); } \
        else { gagal++; printf("[GAGAL] %s\n", nama); }     \
    } while (0)

static int hampir_sama(double a, double b) {
    return fabs(a - b) < 1e-9;
}

static void test_baca_csv(void) {
    /* Buat file CSV test. */
    FILE *f = fopen("/tmp/test_p5.csv", "w");
    fputs("nama,umur,gaji\n", f);
    fputs("Budi,25,5000\n", f);
    fputs("Siti,30,7500\n", f);
    fputs("Andi,28,6200\n", f);
    fclose(f);

    CsvTable tabel;
    CsvStatus s = csv_baca("/tmp/test_p5.csv", &tabel);
    PERIKSA(s == CSV_OK, "Baca CSV berhasil");
    PERIKSA(tabel.jumlah_baris == 4, "Jumlah baris = 4 (1 header + 3 data)");
    PERIKSA(tabel.baris[0].jumlah_field == 3, "Header punya 3 field");
    PERIKSA(strcmp(tabel.baris[1].fields[0], "Budi") == 0,
           "Baris 1 field 0 = 'Budi'");
}

static void test_baca_file_tidak_ada(void) {
    CsvTable tabel;
    CsvStatus s = csv_baca("/tmp/tidak_ada_p5.csv", &tabel);
    PERIKSA(s == CSV_ERR_BUKA_FILE, "File tidak ada -> BUKA_FILE");
}

static void test_parser_ke_double(void) {
    double v;
    PERIKSA(parser_ke_double("3.14", &v) == PARSER_OK && hampir_sama(v, 3.14),
           "Parse '3.14' -> 3.14");
    PERIKSA(parser_ke_double("  42  ", &v) == PARSER_OK && hampir_sama(v, 42.0),
           "Parse '  42  ' -> 42 (toleransi whitespace)");
    PERIKSA(parser_ke_double("bukan-angka", &v) == PARSER_ERR_KONVERSI,
           "Parse 'bukan-angka' -> KONVERSI error");
    PERIKSA(parser_ke_double("", &v) == PARSER_ERR_KONVERSI,
           "Parse string kosong -> KONVERSI error");
}

static void test_statistik_kolom(void) {
    FILE *f = fopen("/tmp/test_p5_stat.csv", "w");
    fputs("nama,nilai\n", f);
    fputs("A,10\n", f);
    fputs("B,20\n", f);
    fputs("C,30\n", f);
    fclose(f);

    CsvTable tabel;
    csv_baca("/tmp/test_p5_stat.csv", &tabel);

    Statistik stat;
    ParserStatus ps = parser_statistik_kolom(&tabel, 1, 1, &stat);
    PERIKSA(ps == PARSER_OK, "Statistik kolom 1 (skip header) berhasil");
    PERIKSA(stat.jumlah == 3, "Jumlah data = 3");
    PERIKSA(hampir_sama(stat.jumlah_nilai, 60.0), "Total = 60");
    PERIKSA(hampir_sama(stat.minimum, 10.0), "Minimum = 10");
    PERIKSA(hampir_sama(stat.maksimum, 30.0), "Maksimum = 30");
    PERIKSA(hampir_sama(stat.rata_rata, 20.0), "Rata-rata = 20");
}

static void test_statistik_kolom_invalid(void) {
    FILE *f = fopen("/tmp/test_p5_bad.csv", "w");
    fputs("nama,umur\n", f);
    fputs("Budi,bukan-umur\n", f);
    fclose(f);

    CsvTable tabel;
    csv_baca("/tmp/test_p5_bad.csv", &tabel);
    Statistik stat;
    ParserStatus ps = parser_statistik_kolom(&tabel, 1, 1, &stat);
    PERIKSA(ps == PARSER_ERR_KONVERSI, "Field non-numerik -> KONVERSI error");
}

int main(void) {
    test_baca_csv();
    test_baca_file_tidak_ada();
    test_parser_ke_double();
    test_statistik_kolom();
    test_statistik_kolom_invalid();
    printf("\nRingkasan: %d lulus, %d gagal\n", lulus, gagal);
    return gagal == 0 ? 0 : 1;
}
