#include "dirpicker.h"

#include <dirent.h>
#include <ncurses.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

#include "colors.h"
#include "icons.h"
#include "util.h"

#define MAX_ENTRIES 1024
#define NAME_CAP 256

static int cmp_names(const void *a, const void *b) {
    return strcasecmp((const char *)a, (const char *)b);
}

static int list_subdirs(const char *dir, char entries[][NAME_CAP], int max) {
    DIR *d = opendir(dir);
    if (!d) return 0;
    int n = 0;
    struct dirent *de;
    while (n < max && (de = readdir(d)) != NULL) {
        if (de->d_name[0] == '.') continue;
        char full[2048];
        snprintf(full, sizeof(full), "%s/%s", dir, de->d_name);
        struct stat st;
        if (stat(full, &st) != 0 || !S_ISDIR(st.st_mode)) continue;
        safe_strcpy(entries[n], NAME_CAP, de->d_name);
        n++;
    }
    closedir(d);
    qsort(entries, n, NAME_CAP, cmp_names);
    return n;
}

static void nearest_existing_dir(const char *start, char *out, size_t cap) {
    char path[1024];
    safe_strcpy(path, sizeof(path), start);
    struct stat st;
    while (stat(path, &st) != 0 || !S_ISDIR(st.st_mode)) {
        char *slash = strrchr(path, '/');
        if (!slash || slash == path) {
            safe_strcpy(path, sizeof(path), getenv("HOME") ? getenv("HOME") : "/");
            break;
        }
        *slash = '\0';
        if (path[0] == '\0') safe_strcpy(path, sizeof(path), "/");
    }
    safe_strcpy(out, cap, path);
}

static void go_to_parent(char *dir) {
    if (strcmp(dir, "/") == 0) return;
    char *slash = strrchr(dir, '/');
    if (!slash) return;
    if (slash == dir) {
        dir[1] = '\0';
    } else {
        *slash = '\0';
    }
}

int dirpicker_run(const char *start_path, char *chosen, size_t cap) {
    char current_dir[1024];
    nearest_existing_dir(start_path, current_dir, sizeof(current_dir));

    static char entries[MAX_ENTRIES][NAME_CAP];
    int entry_count = list_subdirs(current_dir, entries, MAX_ENTRIES);
    int selected = 0;

    int rows, cols;
    getmaxyx(stdscr, rows, cols);
    int win_h = rows * 4 / 5;
    int win_w = cols * 4 / 5;
    int win_y = (rows - win_h) / 2;
    int win_x = (cols - win_w) / 2;

    WINDOW *win = newwin(win_h, win_w, win_y, win_x);
    keypad(win, TRUE);

    int result = 0;
    int running = 1;
    while (running) {
        werase(win);
        draw_rounded_box(win, PAIR_BORDER_FOCUS);
        wattron(win, A_BOLD);
        mvwprintw(win, 0, 2, " Choose a folder to save downloads to ");
        wattroff(win, A_BOLD);

        mvwprintw(win, 1, 2, "Current: %.*s", win_w - 14, current_dir);

        int list_top = 3;
        int list_h = win_h - list_top - 3;
        int start_idx = 0;
        if (selected >= list_h) start_idx = selected - list_h + 1;

        if (entry_count == 0) {
            wattron(win, A_DIM);
            mvwprintw(win, list_top, 4, "(no subfolders)");
            wattroff(win, A_DIM);
        }
        for (int row = 0; row < list_h && start_idx + row < entry_count; row++) {
            int idx = start_idx + row;
            if (idx == selected) wattron(win, A_REVERSE);
            wattron(win, COLOR_PAIR(PAIR_STATUS_PENDING));
            mvwprintw(win, list_top + row, 2, "%s", ICON_FOLDER);
            wattroff(win, COLOR_PAIR(PAIR_STATUS_PENDING));
            mvwprintw(win, list_top + row, 4, "%.*s", win_w - 8, entries[idx]);
            if (idx == selected) wattroff(win, A_REVERSE);
        }

        wattron(win, A_DIM);
        mvwprintw(win, win_h - 2, 2,
                  "Up/Down move  Enter/Right open  Backspace/Left up  s select  Esc cancel");
        wattroff(win, A_DIM);
        wnoutrefresh(win);
        doupdate();

        int ch = wgetch(win);
        switch (ch) {
            case KEY_UP:
                if (selected > 0) selected--;
                break;
            case KEY_DOWN:
                if (selected < entry_count - 1) selected++;
                break;
            case KEY_RIGHT:
            case '\n':
            case '\r':
            case KEY_ENTER:
                if (entry_count > 0) {
                    char next[1024 + NAME_CAP];
                    snprintf(next, sizeof(next), "%s/%s", current_dir, entries[selected]);
                    safe_strcpy(current_dir, sizeof(current_dir), next);
                    entry_count = list_subdirs(current_dir, entries, MAX_ENTRIES);
                    selected = 0;
                }
                break;
            case KEY_LEFT:
            case KEY_BACKSPACE:
            case 127:
            case 8:
                go_to_parent(current_dir);
                entry_count = list_subdirs(current_dir, entries, MAX_ENTRIES);
                selected = 0;
                break;
            case 's':
            case 'S':
                safe_strcpy(chosen, cap, current_dir);
                result = 1;
                running = 0;
                break;
            case 27: /* Esc */
                running = 0;
                break;
            default:
                break;
        }
    }

    delwin(win);
    return result;
}
