#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "core.h"
#include "runner.h"
#include "util.h"

void tui_mode(void);
int cli_mode(int argc, char **argv);
void help(void);

int main(int argc, char **argv) {
    if (argc == 1) {
        tui_mode();
        return 0;
    }
    if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) {
        help();
        return 0;
    }
    if (strcmp(argv[1], "-r") == 0 && argc == 3) {
        return runner_exec(argv[2]);
    }
    if (strcmp(argv[1], "-i") == 0) {
        return cli_mode(argc, argv);
    }
    fprintf(stderr, "error: unknown argument\n");
    help();
    return 1;
}

void help(void) {
    printf("ShellToAssembly v1.1\n\n");
    printf("  ./shelltoassembly                  interactive mode\n");
    printf("  ./shelltoassembly -i in.sh -o out  compile mode\n");
    printf("  ./shelltoassembly -i in.sh -o out -O2\n");
    printf("  ./shelltoassembly -r file           run mode\n");
    printf("  ./shelltoassembly -h                help\n");
}

void tui_mode(void) {
    Config cfg = {0};
    char input[512], out_dir[512], out_name[256], confirm[8], optbuf[8];
    printf("\n  ShellToAssembly v1.1\n");
    printf("  ------------------------\n\n");
    while (1) {
        printf("script path: ");
        fflush(stdout);
        if (!fgets(input, sizeof(input), stdin)) return;
        util_trim_newline(input);
        if (input[0] == '/') break;
        printf("  must be absolute path\n");
    }
    char *dir = util_dirname(input);
    printf("output dir [%s]: ", dir);
    fflush(stdout);
    if (fgets(out_dir, sizeof(out_dir), stdin)) {
        util_trim_newline(out_dir);
        if (strlen(out_dir) == 0) strcpy(out_dir, dir);
    }
    char *base = util_strip_ext(util_basename(input));
    printf("output name [%s]: ", base);
    fflush(stdout);
    if (fgets(out_name, sizeof(out_name), stdin)) {
        util_trim_newline(out_name);
        if (strlen(out_name) == 0) strcpy(out_name, base);
    }
    printf("optimization level [1/2]: ");
    fflush(stdout);
    if (fgets(optbuf, sizeof(optbuf), stdin)) {
        util_trim_newline(optbuf);
        cfg.optimize_level = (optbuf[0] == '2') ? 2 : 1;
    } else {
        cfg.optimize_level = 1;
    }
    static char full[1024];
    snprintf(full, sizeof(full), "%s/%s", out_dir, out_name);
    printf("\ninput : %s\n", input);
    printf("output: %s\n", full);
    printf("level : O%d\n", cfg.optimize_level);
    printf("compile? (y/n): ");
    fflush(stdout);
    if (!fgets(confirm, sizeof(confirm), stdin)) return;
    if (confirm[0] != 'y' && confirm[0] != 'Y') {
        printf("cancelled\n");
        return;
    }
    cfg.input = input;
    cfg.output = full;
    printf("\ncompiling...\n");
    int ok = core_compile(&cfg);
    if (ok == 0) {
        chmod(full, 0755);
        printf("done\n");
    } else {
        printf("failed\n");
    }
}

int cli_mode(int argc, char **argv) {
    Config cfg = {0};
    cfg.optimize_level = 1;
    if (argc < 3) {
        fprintf(stderr, "error: -i requires input file\n");
        return 1;
    }
    cfg.input = argv[2];
    for (int i = 3; i < argc; i++) {
        if (strcmp(argv[i], "-o") == 0 && i + 1 < argc) {
            cfg.output = argv[++i];
        } else if (strcmp(argv[i], "-O1") == 0) {
            cfg.optimize_level = 1;
        } else if (strcmp(argv[i], "-O2") == 0) {
            cfg.optimize_level = 2;
        }
    }
    if (!util_file_exists(cfg.input)) {
        fprintf(stderr, "error: file not found: %s\n", cfg.input);
        return 1;
    }
    if (!cfg.output) {
        char *base = util_strip_ext(util_basename(cfg.input));
        char *dir = util_dirname(cfg.input);
        static char out[512];
        snprintf(out, sizeof(out), "%s/%s", dir, base);
        cfg.output = out;
    }
    printf("input : %s\n", cfg.input);
    printf("output: %s\n", cfg.output);
    printf("level : O%d\n", cfg.optimize_level);
    int ret = core_compile(&cfg);
    if (ret == 0) chmod(cfg.output, 0755);
    return ret;
}
