/* storage.c - Implementasi persistensi CSV untuk Finance */
#include "storage.h"

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

static void strip_newline(char *s) {
    size_t len = strlen(s);
    while (len > 0 && (s[len - 1] == '\n' || s[len - 1] == '\r')) {
        s[--len] = '\0';
    }
}

/* Parse satu baris CSV dengan field yang mungkin mengandung koma
 * jika dibungkus tanda kutip. Implementasi sederhana: kita asumsikan
 * description dan category tidak mengandung koma. */
static int parse_line(const char *line, int *id, int *type,
                      double *amount, char *desc, size_t desc_cap,
                      char *cat, size_t cat_cap, char *date, size_t date_cap) {
    char tmp_desc[TXN_DESC_MAX];
    char tmp_cat[TXN_CATEGORY_MAX];
    char tmp_date[16];
    int consumed = 0;
    int items = sscanf(line, "%d,%d,%lf,%63[^,],%31[^,],%10s%n",
                       id, type, amount, tmp_desc, tmp_cat, tmp_date,
                       &consumed);
    if (items != 6) {
        return 0;
    }
    char trailing = line[consumed];
    if (trailing != '\0' && trailing != '\n' && trailing != '\r') {
        return 0;
    }
    if (desc_cap < sizeof(tmp_desc) || cat_cap < sizeof(tmp_cat) ||
        date_cap < sizeof(tmp_date)) {
        return 0;
    }
    strcpy(desc, tmp_desc);
    strcpy(cat, tmp_cat);
    strcpy(date, tmp_date);
    return 1;
}

int storage_save(const Finance *f, const char *path) {
    if (f == NULL || path == NULL) {
        return -1;
    }
    FILE *fp = fopen(path, "w");
    if (fp == NULL) {
        return -1;
    }
    fprintf(fp, "# id,type,amount,description,category,date\n");
    int written = 0;
    for (int i = 0; i < f->count; i++) {
        const Transaction *t = &f->items[i];
        int n = fprintf(fp, "%d,%d,%.2f,%s,%s,%s\n",
                        t->id, t->type, t->amount,
                        t->description, t->category, t->date);
        if (n < 0) {
            fclose(fp);
            return -1;
        }
        written++;
    }
    fclose(fp);
    return written;
}

int storage_load(Finance *f, const char *path) {
    if (f == NULL || path == NULL) {
        return -1;
    }
    FILE *fp = fopen(path, "r");
    if (fp == NULL) {
        return -1;
    }
    finance_init(f);
    char line[256];
    int read = 0;
    int max_id_seen = 0;
    while (fgets(line, sizeof(line), fp) != NULL) {
        if (line[0] == '#' || line[0] == '\n' || line[0] == '\r') {
            continue;
        }
        strip_newline(line);
        int id, type;
        double amount;
        char desc[TXN_DESC_MAX];
        char cat[TXN_CATEGORY_MAX];
        char date[16];
        if (!parse_line(line, &id, &type, &amount, desc, sizeof(desc),
                       cat, sizeof(cat), date, sizeof(date))) {
            continue;
        }
        if (f->count >= FINANCE_CAPACITY) {
            break;
        }
        if (type != TXN_INCOME && type != TXN_EXPENSE) {
            continue;
        }
        Transaction *slot = &f->items[f->count];
        if (transaction_create(slot, id, (TxnType)type, amount,
                               desc, cat, date) != 0) {
            continue;
        }
        if (id > max_id_seen) {
            max_id_seen = id;
        }
        f->count++;
        read++;
    }
    f->next_id = max_id_seen + 1;
    fclose(fp);
    return read;
}
