/*
  Merge compact 66-zone outputs into one long database CSV.

  Usage:
    tsunami_merge_forecast66.exe merged_db.csv result1.csv result2.csv ...

  Output rows:
    scenario_id,source_file,run_time_s,forecast_zone_id,forecast_zone_name,
    first_arrival_s,first_arrival_min,max_height_m,max_height_cm,warning_bin,warning_color_hex,station_count
*/

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

static char *trim(char *s) {
    if ((unsigned char)s[0] == 0xEF && (unsigned char)s[1] == 0xBB && (unsigned char)s[2] == 0xBF) s += 3;
    while (*s && isspace((unsigned char)*s)) s++;
    char *e = s + strlen(s);
    while (e > s && isspace((unsigned char)e[-1])) *--e = '\0';
    return s;
}

static void csv_write_escaped(FILE *fp, const char *text) {
    fputc('"', fp);
    for (const unsigned char *p = (const unsigned char *)text; *p; ++p) {
        if (*p == '"') fputc('"', fp);
        fputc(*p, fp);
    }
    fputc('"', fp);
}

static void strip_outer_quotes(char *s) {
    size_t n = strlen(s);
    if (n >= 2 && s[0] == '"' && s[n-1] == '"') {
        memmove(s, s + 1, n - 2);
        s[n-2] = '\0';
    }
}

static void parse_meta_value(char *line, const char *key, char *out, size_t out_sz) {
    size_t klen = strlen(key);
    char *p = trim(line);
    if (strncmp(p, "# ", 2) == 0) p += 2;
    if (strncmp(p, key, klen) != 0) return;
    p += klen;
    if (*p == ',') p++;
    p = trim(p);
    strip_outer_quotes(p);
    snprintf(out, out_sz, "%s", p);
}

static int merge_one(FILE *out, const char *path) {
    FILE *fp = fopen(path, "rb");
    if (!fp) {
        fprintf(stderr, "Cannot open: %s\n", path);
        return 0;
    }
    char scenario_id[256] = "";
    char source_file[512] = "";
    char run_time_s[64] = "";
    char line[8192];
    int in_table = 0;
    int rows = 0;
    while (fgets(line, sizeof(line), fp)) {
        char tmp[8192];
        snprintf(tmp, sizeof(tmp), "%s", line);
        char *p = trim(tmp);
        if (*p == '\0') continue;
        if (*p == '#') {
            parse_meta_value(p, "scenario_id", scenario_id, sizeof(scenario_id));
            parse_meta_value(p, "source_file", source_file, sizeof(source_file));
            parse_meta_value(p, "run_time_s", run_time_s, sizeof(run_time_s));
            continue;
        }
        if (strncmp(p, "forecast_zone_id", 16) == 0) {
            in_table = 1;
            continue;
        }
        if (!in_table) continue;
        csv_write_escaped(out, scenario_id[0] ? scenario_id : path);
        fputc(',', out);
        csv_write_escaped(out, source_file);
        fputc(',', out);
        fprintf(out, "%s,%s\n", run_time_s[0] ? run_time_s : "", p);
        rows++;
    }
    fclose(fp);
    fprintf(stderr, "Merged %d rows: %s\n", rows, path);
    return rows > 0;
}

int main(int argc, char **argv) {
    if (argc < 3) {
        fprintf(stderr, "Usage: %s merged_db.csv result1.csv result2.csv ...\n", argv[0]);
        return 2;
    }
    FILE *out = fopen(argv[1], "wb");
    if (!out) {
        fprintf(stderr, "Cannot write: %s\n", argv[1]);
        return 1;
    }
    fputs("\xEF\xBB\xBF", out);
    fprintf(out, "scenario_id,source_file,run_time_s,forecast_zone_id,forecast_zone_name,first_arrival_s,first_arrival_min,max_height_m,max_height_cm,warning_bin,warning_color_hex,station_count\n");
    int ok = 0;
    for (int i = 2; i < argc; ++i) ok += merge_one(out, argv[i]);
    fclose(out);
    fprintf(stderr, "Merged files: %d/%d -> %s\n", ok, argc - 2, argv[1]);
    return ok ? 0 : 1;
}
