#include "board.h"
#include "json.h"
#include "search.h"

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

static void usage(void) {
    fprintf(stderr,
            "Usage: procon_solver_v1 --input <puzzle.json> [--output ops.json] [--width N] [--depth N] [--nlimit N]\n"
            "  --width   Beam width (default 200)\n"
            "  --depth   Max search depth (default 25)\n"
            "  --nlimit  Max rotation size considered (default 4)\n"
            "  --output  Write ops JSON to file (default: stdout)\n");
}

static void write_ops_json(FILE *fp, const Solution *sol) {
    fprintf(fp, "{\n  \"ops\": [\n");
    for (int i = 0; i < sol->len; ++i) {
        const Move *m = &sol->moves[i];
        fprintf(fp, "    {\"x\": %u, \"y\": %u, \"n\": %u}%s\n",
                m->x, m->y, m->n, (i + 1 == sol->len) ? "" : ",");
    }
    fprintf(fp, "  ]\n}\n");
}

int main(int argc, char **argv) {
    const char *input = NULL;
    const char *output = NULL;
    int width = 200;
    int depth = 25;
    int nlimit = 4;

    for (int i = 1; i < argc; ++i) {
        if (strcmp(argv[i], "--input") == 0 && i + 1 < argc) {
            input = argv[++i];
        } else if (strcmp(argv[i], "--output") == 0 && i + 1 < argc) {
            output = argv[++i];
        } else if (strcmp(argv[i], "--width") == 0 && i + 1 < argc) {
            width = atoi(argv[++i]);
        } else if (strcmp(argv[i], "--depth") == 0 && i + 1 < argc) {
            depth = atoi(argv[++i]);
        } else if (strcmp(argv[i], "--nlimit") == 0 && i + 1 < argc) {
            nlimit = atoi(argv[++i]);
        } else if (strcmp(argv[i], "--help") == 0) {
            usage();
            return 0;
        } else {
            usage();
            return 1;
        }
    }

    if (!input) {
        usage();
        return 1;
    }

    Board start;
    if (load_puzzle(input, &start) != 0) {
        return 1;
    }

    Solution sol = {0};
    if (solve_beam(&start, width, depth, nlimit, &sol) != 0) {
        fprintf(stderr, "Solve failed.\n");
        return 1;
    }

    FILE *fp = stdout;
    if (output) {
        fp = fopen(output, "wb");
        if (!fp) {
            fprintf(stderr, "Failed to open output file: %s\n", output);
            return 1;
        }
    }
    write_ops_json(fp, &sol);
    if (output) fclose(fp);

    fprintf(stderr, "Pairs: %d -> %d using %d moves\n", start.pair_count, sol.pair_count, sol.len);
    return 0;
}
