/* tests.c -- rangkaian test untuk modul task dan storage. */

#include "task.h"
#include "storage.h"

#include <stdio.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 void test_tambah(void) {
    TaskList list;
    task_list_init(&list);
    TaskResult r1 = task_tambah(&list, "Belajar C", "Bab struct", TASK_PRIORITAS_TINGGI);
    TaskResult r2 = task_tambah(&list, "Belanja", "Beli susu", TASK_PRIORITAS_SEDANG);
    PERIKSA(r1 == TASK_OK && r2 == TASK_OK, "Tambah 2 tugas berhasil");
    PERIKSA(list.jumlah == 2, "Jumlah = 2");
    PERIKSA(list.data[0].id == 1, "ID pertama = 1");
    PERIKSA(list.data[0].status == TASK_STATUS_BELUM, "Status awal = BELUM");
}

static void test_tambah_invalid(void) {
    TaskList list;
    task_list_init(&list);
    PERIKSA(task_tambah(&list, "", "x", TASK_PRIORITAS_SEDANG) == TASK_ERR_INPUT_INVALID,
           "Judul kosong ditolak");
    PERIKSA(task_tambah(&list, "X", "Y", (TaskPrioritas)99) == TASK_ERR_INPUT_INVALID,
           "Prioritas invalid ditolak");
    PERIKSA(list.jumlah == 0, "Tidak ada tugas ditambahkan");
}

static void test_set_status(void) {
    TaskList list;
    task_list_init(&list);
    task_tambah(&list, "T1", "D1", TASK_PRIORITAS_SEDANG);
    TaskResult r = task_set_status(&list, 1, TASK_STATUS_SELESAI);
    PERIKSA(r == TASK_OK, "Set status SELESAI berhasil");
    PERIKSA(list.data[0].status == TASK_STATUS_SELESAI, "Status = SELESAI");
    PERIKSA(task_set_status(&list, 999, TASK_STATUS_PROSES) == TASK_ERR_TIDAK_DITEMUKAN,
           "Set status ID tidak ada -> error");
}

static void test_hapus(void) {
    TaskList list;
    task_list_init(&list);
    task_tambah(&list, "T1", "D1", TASK_PRIORITAS_SEDANG);
    task_tambah(&list, "T2", "D2", TASK_PRIORITAS_SEDANG);
    task_tambah(&list, "T3", "D3", TASK_PRIORITAS_SEDANG);
    TaskResult r = task_hapus(&list, 2);
    PERIKSA(r == TASK_OK && list.jumlah == 2, "Hapus id=2 berhasil");
    PERIKSA(strcmp(list.data[1].judul, "T3") == 0,
           "Setelah hapus, elemen 1 = 'T3'");
}

static void test_filter_status(void) {
    TaskList list;
    task_list_init(&list);
    task_tambah(&list, "T1", "D1", TASK_PRIORITAS_SEDANG);   /* BELUM */
    task_tambah(&list, "T2", "D2", TASK_PRIORITAS_SEDANG);
    task_tambah(&list, "T3", "D3", TASK_PRIORITAS_SEDANG);
    task_set_status(&list, 2, TASK_STATUS_PROSES);
    task_set_status(&list, 3, TASK_STATUS_SELESAI);

    int n = task_filter_status(&list, TASK_STATUS_PROSES, stdout);
    PERIKSA(n == 1, "Filter PROSES menemukan 1 tugas");
}

static void test_cari(void) {
    TaskList list;
    task_list_init(&list);
    task_tambah(&list, "Belajar C", "", TASK_PRIORITAS_SEDANG);
    task_tambah(&list, "Belajar Python", "", TASK_PRIORITAS_SEDANG);
    int idx = task_cari(&list, "Python");
    PERIKSA(idx == 1, "Cari 'Python' -> indeks 1");
    PERIKSA(task_cari(&list, "Rust") == -1, "Cari 'Rust' -> -1");
}

static void test_penyimpanan(void) {
    TaskList list;
    task_list_init(&list);
    task_tambah(&list, "T1", "D1", TASK_PRIORITAS_TINGGI);
    task_tambah(&list, "T2", "D2", TASK_PRIORITAS_RENDAH);
    task_set_status(&list, 2, TASK_STATUS_SELESAI);

    StorageStatus ss = storage_simpan(&list, "/tmp/test_tugas.txt");
    PERIKSA(ss == STORAGE_OK, "Simpan ke /tmp/test_tugas.txt");

    TaskList dimuat;
    task_list_init(&dimuat);
    ss = storage_muat(&dimuat, "/tmp/test_tugas.txt");
    PERIKSA(ss == STORAGE_OK, "Muat dari /tmp/test_tugas.txt");
    PERIKSA(dimuat.jumlah == 2, "Jumlah dimuat = 2");
    PERIKSA(strcmp(dimuat.data[0].judul, "T1") == 0, "Judul dimuat = 'T1'");
    PERIKSA(dimuat.data[1].status == TASK_STATUS_SELESAI, "Status dimuat = SELESAI");
    PERIKSA(dimuat.id_berikutnya == 3, "id_berikutnya = 3");
}

int main(void) {
    test_tambah();
    test_tambah_invalid();
    test_set_status();
    test_hapus();
    test_filter_status();
    test_cari();
    test_penyimpanan();
    printf("\nRingkasan: %d lulus, %d gagal\n", lulus, gagal);
    return gagal == 0 ? 0 : 1;
}
