/*
    * dialogs.cpp
    * User-management dialogs for the embedded desktop user management applet
    * Copyright (c) 2026 Daniel Hammer
*/

#include "usermanager_internal.hpp"

namespace usermanager_app {

static mtk::WidgetState dialog_button_state(int mouse_x, int mouse_y,
                                            const Rect& rect,
                                            bool enabled = true,
                                            bool active = false) {
    return mtk::widget_state(active, rect.contains(mouse_x, mouse_y), enabled);
}

static void dialog_close_self(DesktopState* ds, void* app_data) {
    for (int i = 0; i < ds->window_count; i++) {
        if (ds->windows[i].app_data == app_data) {
            desktop_close_window(ds, i);
            return;
        }
    }
}

static Rect dialog_primary_button_rect(int pad, int content_h) {
    return {pad, content_h - USER_BTN_H - pad, 80, USER_BTN_H};
}

static Rect dialog_secondary_button_rect(int pad, int content_h) {
    return {pad + 88, content_h - USER_BTN_H - pad, 80, USER_BTN_H};
}

struct AddUserDialogState {
    DesktopState* ds;
    UserManagerState* parent;
    Color accent;
    int mouse_x;
    int mouse_y;
    int field;
    char username[32];      int username_len;
    mtk::TextInputState username_input;
    char display[64];       int display_len;
    mtk::TextInputState display_input;
    char password[64];      int password_len;
    mtk::TextInputState password_input;
    bool role_admin;
    char error[64];
};

static void adduser_on_draw(Window* win, Framebuffer& fb) {
    (void)fb;
    AddUserDialogState* st = (AddUserDialogState*)win->app_data;
    if (!st) return;

    Canvas c(win);
    mtk::Theme theme = mtk::make_theme(st->accent);
    c.fill(theme.window_bg);

    int pad = 16;
    int fw = c.w - 2 * pad;
    int y = pad;
    int sfh = system_font_height();

    mtk::draw_labeled_text_field(c, pad, y, fw, "Username", st->username,
                                 st->username_input.cursor, st->field == 0, false,
                                 theme, USER_FIELD_H, st->username_input.selection_anchor);
    y += mtk::labeled_text_height(theme, USER_FIELD_H) + 10;

    mtk::draw_labeled_text_field(c, pad, y, fw, "Display Name", st->display,
                                 st->display_input.cursor, st->field == 1, false,
                                 theme, USER_FIELD_H, st->display_input.selection_anchor);
    y += mtk::labeled_text_height(theme, USER_FIELD_H) + 10;

    mtk::draw_labeled_text_field(c, pad, y, fw, "Password", st->password,
                                 st->password_input.cursor, st->field == 2, true,
                                 theme, USER_FIELD_H, st->password_input.selection_anchor);
    y += mtk::labeled_text_height(theme, USER_FIELD_H) + 12;

    c.text(pad, y + 4, "Role:", theme.text_muted);
    Rect user_btn = {pad + 60, y, 60, USER_BTN_H};
    Rect admin_btn = {pad + 128, y, 60, USER_BTN_H};
    mtk::draw_button(c, user_btn, "User", mtk::BUTTON_SECONDARY,
                     dialog_button_state(st->mouse_x, st->mouse_y, user_btn, true, !st->role_admin),
                     theme);
    mtk::draw_button(c, admin_btn, "Admin", mtk::BUTTON_SECONDARY,
                     dialog_button_state(st->mouse_x, st->mouse_y, admin_btn, true, st->role_admin),
                     theme);
    y += USER_BTN_H + 14;

    if (st->error[0]) {
        c.text(pad, y, st->error, theme.danger);
        y += sfh + 6;
    }

    Rect create_btn = dialog_primary_button_rect(pad, c.h);
    Rect cancel_btn = dialog_secondary_button_rect(pad, c.h);
    mtk::draw_modal_actions(c,
                            create_btn, "Create",
                            mtk::BUTTON_PRIMARY,
                            dialog_button_state(st->mouse_x, st->mouse_y, create_btn),
                            cancel_btn, "Cancel",
                            dialog_button_state(st->mouse_x, st->mouse_y, cancel_btn),
                            theme);

    mtk::draw_text_input_context_menu(
        c, st->username_input, theme,
        mtk::text_input_has_selection(st->username_input,
                                      st->username, (int)sizeof(st->username)));
    mtk::draw_text_input_context_menu(
        c, st->display_input, theme,
        mtk::text_input_has_selection(st->display_input,
                                      st->display, (int)sizeof(st->display)));
    mtk::draw_text_input_context_menu(
        c, st->password_input, theme,
        mtk::text_input_has_selection(st->password_input,
                                      st->password, (int)sizeof(st->password)),
        true);
}

static void adduser_submit(AddUserDialogState* st) {
    if (st->username_len == 0) {
        montauk::strcpy(st->error, "Username is required");
        return;
    }
    if (st->password_len == 0) {
        montauk::strcpy(st->error, "Password is required");
        return;
    }

    const char* dname = st->display_len > 0 ? st->display : st->username;
    const char* role = st->role_admin ? "admin" : "user";
    if (montauk::user::create_user(st->username, dname, st->password, role)) {
        st->parent->users_loaded = false;
        usermanager_set_status(st->parent, "User created");
        dialog_close_self(st->ds, st);
    } else {
        montauk::strcpy(st->error, "Failed (username taken?)");
    }
}

static void adduser_on_mouse(Window* win, MouseEvent& ev) {
    AddUserDialogState* st = (AddUserDialogState*)win->app_data;
    if (!st) return;

    mtk::DesktopHost host(win);
    int mx = 0;
    int my = 0;
    if (!host.map_mouse(ev, &mx, &my)) return;
    st->mouse_x = mx;
    st->mouse_y = my;

    mtk::Theme theme = mtk::make_theme(st->accent);
    int pad = 16;
    int fw = win->content_w - 2 * pad;
    int y = pad;
    bool right_pressed = ev.right_pressed();

    Rect username_rect = mtk::labeled_text_input_rect(pad, y, fw, theme, USER_FIELD_H);
    if (st->username_input.context.open || st->username_input.dragging) {
        int result = mtk::text_input_handle_mouse(
            st->username_input, username_rect, st->username, (int)sizeof(st->username),
            mx, my, ev.buttons, ev.prev_buttons, win->content_w, win->content_h,
            st->field == 0);
        if (result & mtk::TEXT_INPUT_CHANGED)
            st->username_len = mtk::text_input_len(st->username, (int)sizeof(st->username));
        return;
    }
    y += mtk::labeled_text_height(theme, USER_FIELD_H) + 10;

    Rect display_rect = mtk::labeled_text_input_rect(pad, y, fw, theme, USER_FIELD_H);
    if (st->display_input.context.open || st->display_input.dragging) {
        int result = mtk::text_input_handle_mouse(
            st->display_input, display_rect, st->display, (int)sizeof(st->display),
            mx, my, ev.buttons, ev.prev_buttons, win->content_w, win->content_h,
            st->field == 1);
        if (result & mtk::TEXT_INPUT_CHANGED)
            st->display_len = mtk::text_input_len(st->display, (int)sizeof(st->display));
        return;
    }
    y += mtk::labeled_text_height(theme, USER_FIELD_H) + 10;

    Rect password_rect = mtk::labeled_text_input_rect(pad, y, fw, theme, USER_FIELD_H);
    if (st->password_input.context.open || st->password_input.dragging) {
        int result = mtk::text_input_handle_mouse(
            st->password_input, password_rect, st->password, (int)sizeof(st->password),
            mx, my, ev.buttons, ev.prev_buttons, win->content_w, win->content_h,
            st->field == 2, true);
        if (result & mtk::TEXT_INPUT_CHANGED)
            st->password_len = mtk::text_input_len(st->password, (int)sizeof(st->password));
        return;
    }
    y += mtk::labeled_text_height(theme, USER_FIELD_H) + 12;

    if (!ev.left_pressed() && !right_pressed) return;

    if (username_rect.contains(mx, my)) {
        st->field = 0;
        mtk::context_menu_close(st->display_input.context);
        mtk::context_menu_close(st->password_input.context);
        int result = mtk::text_input_handle_mouse(
            st->username_input, username_rect, st->username, (int)sizeof(st->username),
            mx, my, ev.buttons, ev.prev_buttons, win->content_w, win->content_h,
            true);
        if (result & mtk::TEXT_INPUT_CHANGED)
            st->username_len = mtk::text_input_len(st->username, (int)sizeof(st->username));
        return;
    }
    if (display_rect.contains(mx, my)) {
        st->field = 1;
        mtk::context_menu_close(st->username_input.context);
        mtk::context_menu_close(st->password_input.context);
        int result = mtk::text_input_handle_mouse(
            st->display_input, display_rect, st->display, (int)sizeof(st->display),
            mx, my, ev.buttons, ev.prev_buttons, win->content_w, win->content_h,
            true);
        if (result & mtk::TEXT_INPUT_CHANGED)
            st->display_len = mtk::text_input_len(st->display, (int)sizeof(st->display));
        return;
    }
    if (password_rect.contains(mx, my)) {
        st->field = 2;
        mtk::context_menu_close(st->username_input.context);
        mtk::context_menu_close(st->display_input.context);
        int result = mtk::text_input_handle_mouse(
            st->password_input, password_rect, st->password, (int)sizeof(st->password),
            mx, my, ev.buttons, ev.prev_buttons, win->content_w, win->content_h,
            true, true);
        if (result & mtk::TEXT_INPUT_CHANGED)
            st->password_len = mtk::text_input_len(st->password, (int)sizeof(st->password));
        return;
    }

    if (!ev.left_pressed()) return;

    Rect user_btn = {pad + 60, y, 60, USER_BTN_H};
    Rect admin_btn = {pad + 128, y, 60, USER_BTN_H};
    if (user_btn.contains(mx, my)) {
        st->role_admin = false;
        return;
    }
    if (admin_btn.contains(mx, my)) {
        st->role_admin = true;
        return;
    }

    Rect create_btn = dialog_primary_button_rect(pad, win->content_h);
    Rect cancel_btn = dialog_secondary_button_rect(pad, win->content_h);
    if (create_btn.contains(mx, my)) {
        adduser_submit(st);
        return;
    }
    if (cancel_btn.contains(mx, my)) {
        dialog_close_self(st->ds, st);
        return;
    }
}

static void adduser_on_key(Window* win, const Montauk::KeyEvent& key) {
    AddUserDialogState* st = (AddUserDialogState*)win->app_data;
    if (!st || !key.pressed) return;

    if (key.ascii == '\n' || key.ascii == '\r' || key.scancode == 0x1C) {
        adduser_submit(st);
        return;
    }
    if (key.scancode == 0x01) {
        dialog_close_self(st->ds, st);
        return;
    }
    if (key.scancode == 0x0F) {
        st->field = (st->field + 1) % 3;
        return;
    }

    int result = mtk::TEXT_INPUT_NONE;
    switch (st->field) {
    case 0:
        result = mtk::text_input_key(st->username_input, st->username,
                                     (int)sizeof(st->username), key);
        if (result & mtk::TEXT_INPUT_CHANGED)
            st->username_len = mtk::text_input_len(st->username, (int)sizeof(st->username));
        break;
    case 1:
        result = mtk::text_input_key(st->display_input, st->display,
                                     (int)sizeof(st->display), key);
        if (result & mtk::TEXT_INPUT_CHANGED)
            st->display_len = mtk::text_input_len(st->display, (int)sizeof(st->display));
        break;
    case 2:
        result = mtk::text_input_key(st->password_input, st->password,
                                     (int)sizeof(st->password), key,
                                     nullptr, nullptr, true);
        if (result & mtk::TEXT_INPUT_CHANGED)
            st->password_len = mtk::text_input_len(st->password, (int)sizeof(st->password));
        break;
    }
}

static void adduser_on_close(Window* win) {
    if (win->app_data) {
        montauk::mfree(win->app_data);
        win->app_data = nullptr;
    }
}

void open_add_user_dialog(UserManagerState* parent) {
    DesktopState* ds = parent->desktop;
    int w = 340;
    int h = 340;
    int wx = (ds->screen_w - w) / 2;
    int wy = (ds->screen_h - h) / 2;
    int idx = desktop_create_window(ds, "Add User", wx, wy, w, h);
    if (idx < 0) return;

    Window* win = &ds->windows[idx];
    AddUserDialogState* st = (AddUserDialogState*)montauk::malloc(sizeof(AddUserDialogState));
    montauk::memset(st, 0, sizeof(AddUserDialogState));
    st->ds = ds;
    st->parent = parent;
    st->accent = ds->settings.accent_color;
    st->mouse_x = -1;
    st->mouse_y = -1;

    win->app_data = st;
    win->on_draw = adduser_on_draw;
    win->on_mouse = adduser_on_mouse;
    win->on_key = adduser_on_key;
    win->on_close = adduser_on_close;
}

struct ChPwdDialogState {
    DesktopState* ds;
    UserManagerState* parent;
    Color accent;
    int mouse_x;
    int mouse_y;
    char username[32];
    char display_name[64];
    int field;
    char new_pwd[64];       int new_len;
    mtk::TextInputState new_input;
    char confirm[64];       int confirm_len;
    mtk::TextInputState confirm_input;
    char error[64];
};

static void chpwd_on_draw(Window* win, Framebuffer& fb) {
    (void)fb;
    ChPwdDialogState* st = (ChPwdDialogState*)win->app_data;
    if (!st) return;

    Canvas c(win);
    mtk::Theme theme = mtk::make_theme(st->accent);
    c.fill(theme.window_bg);

    int pad = 16;
    int fw = c.w - 2 * pad;
    int y = pad;
    int sfh = system_font_height();

    char title[80];
    snprintf(title, sizeof(title), "Change password for %s", st->display_name);
    c.text(pad, y, title, theme.text);
    y += sfh + 12;

    mtk::draw_labeled_text_field(c, pad, y, fw, "New Password", st->new_pwd,
                                 st->new_input.cursor, st->field == 0, true,
                                 theme, USER_FIELD_H, st->new_input.selection_anchor);
    y += mtk::labeled_text_height(theme, USER_FIELD_H) + 10;

    mtk::draw_labeled_text_field(c, pad, y, fw, "Confirm Password", st->confirm,
                                 st->confirm_input.cursor, st->field == 1, true,
                                 theme, USER_FIELD_H, st->confirm_input.selection_anchor);
    y += mtk::labeled_text_height(theme, USER_FIELD_H) + 12;

    if (st->error[0]) {
        c.text(pad, y, st->error, theme.danger);
    }

    Rect save_btn = dialog_primary_button_rect(pad, c.h);
    Rect cancel_btn = dialog_secondary_button_rect(pad, c.h);
    mtk::draw_modal_actions(c,
                            save_btn, "Save",
                            mtk::BUTTON_PRIMARY,
                            dialog_button_state(st->mouse_x, st->mouse_y, save_btn),
                            cancel_btn, "Cancel",
                            dialog_button_state(st->mouse_x, st->mouse_y, cancel_btn),
                            theme);

    mtk::draw_text_input_context_menu(
        c, st->new_input, theme,
        mtk::text_input_has_selection(st->new_input,
                                      st->new_pwd, (int)sizeof(st->new_pwd)),
        true);
    mtk::draw_text_input_context_menu(
        c, st->confirm_input, theme,
        mtk::text_input_has_selection(st->confirm_input,
                                      st->confirm, (int)sizeof(st->confirm)),
        true);
}

static void chpwd_submit(ChPwdDialogState* st) {
    if (st->new_len == 0) {
        montauk::strcpy(st->error, "Password cannot be empty");
        return;
    }
    if (!montauk::streq(st->new_pwd, st->confirm)) {
        montauk::strcpy(st->error, "Passwords don't match");
        return;
    }

    montauk::user::change_password(st->username, st->new_pwd);
    usermanager_set_status(st->parent, "Password changed");
    dialog_close_self(st->ds, st);
}

static void chpwd_on_mouse(Window* win, MouseEvent& ev) {
    ChPwdDialogState* st = (ChPwdDialogState*)win->app_data;
    if (!st) return;

    mtk::DesktopHost host(win);
    int mx = 0;
    int my = 0;
    if (!host.map_mouse(ev, &mx, &my)) return;
    st->mouse_x = mx;
    st->mouse_y = my;

    mtk::Theme theme = mtk::make_theme(st->accent);
    int pad = 16;
    int fw = win->content_w - 2 * pad;
    int y = pad + system_font_height() + 12;
    bool right_pressed = ev.right_pressed();

    Rect new_rect = mtk::labeled_text_input_rect(pad, y, fw, theme, USER_FIELD_H);
    if (st->new_input.context.open || st->new_input.dragging) {
        int result = mtk::text_input_handle_mouse(
            st->new_input, new_rect, st->new_pwd, (int)sizeof(st->new_pwd),
            mx, my, ev.buttons, ev.prev_buttons, win->content_w, win->content_h,
            st->field == 0, true);
        if (result & mtk::TEXT_INPUT_CHANGED)
            st->new_len = mtk::text_input_len(st->new_pwd, (int)sizeof(st->new_pwd));
        return;
    }
    y += mtk::labeled_text_height(theme, USER_FIELD_H) + 10;

    Rect confirm_rect = mtk::labeled_text_input_rect(pad, y, fw, theme, USER_FIELD_H);
    if (st->confirm_input.context.open || st->confirm_input.dragging) {
        int result = mtk::text_input_handle_mouse(
            st->confirm_input, confirm_rect, st->confirm, (int)sizeof(st->confirm),
            mx, my, ev.buttons, ev.prev_buttons, win->content_w, win->content_h,
            st->field == 1, true);
        if (result & mtk::TEXT_INPUT_CHANGED)
            st->confirm_len = mtk::text_input_len(st->confirm, (int)sizeof(st->confirm));
        return;
    }

    if (!ev.left_pressed() && !right_pressed) return;

    if (new_rect.contains(mx, my)) {
        st->field = 0;
        mtk::context_menu_close(st->confirm_input.context);
        int result = mtk::text_input_handle_mouse(
            st->new_input, new_rect, st->new_pwd, (int)sizeof(st->new_pwd),
            mx, my, ev.buttons, ev.prev_buttons, win->content_w, win->content_h,
            true, true);
        if (result & mtk::TEXT_INPUT_CHANGED)
            st->new_len = mtk::text_input_len(st->new_pwd, (int)sizeof(st->new_pwd));
        return;
    }
    if (confirm_rect.contains(mx, my)) {
        st->field = 1;
        mtk::context_menu_close(st->new_input.context);
        int result = mtk::text_input_handle_mouse(
            st->confirm_input, confirm_rect, st->confirm, (int)sizeof(st->confirm),
            mx, my, ev.buttons, ev.prev_buttons, win->content_w, win->content_h,
            true, true);
        if (result & mtk::TEXT_INPUT_CHANGED)
            st->confirm_len = mtk::text_input_len(st->confirm, (int)sizeof(st->confirm));
        return;
    }

    if (!ev.left_pressed()) return;

    Rect save_btn = dialog_primary_button_rect(pad, win->content_h);
    Rect cancel_btn = dialog_secondary_button_rect(pad, win->content_h);
    if (save_btn.contains(mx, my)) {
        chpwd_submit(st);
        return;
    }
    if (cancel_btn.contains(mx, my)) {
        dialog_close_self(st->ds, st);
        return;
    }
}

static void chpwd_on_key(Window* win, const Montauk::KeyEvent& key) {
    ChPwdDialogState* st = (ChPwdDialogState*)win->app_data;
    if (!st || !key.pressed) return;

    if (key.ascii == '\n' || key.ascii == '\r' || key.scancode == 0x1C) {
        chpwd_submit(st);
        return;
    }
    if (key.scancode == 0x01) {
        dialog_close_self(st->ds, st);
        return;
    }
    if (key.scancode == 0x0F) {
        st->field = (st->field + 1) % 2;
        return;
    }
    if (st->field == 0) {
        int result = mtk::text_input_key(st->new_input, st->new_pwd,
                                         (int)sizeof(st->new_pwd), key,
                                         nullptr, nullptr, true);
        if (result & mtk::TEXT_INPUT_CHANGED)
            st->new_len = mtk::text_input_len(st->new_pwd, (int)sizeof(st->new_pwd));
    } else {
        int result = mtk::text_input_key(st->confirm_input, st->confirm,
                                         (int)sizeof(st->confirm), key,
                                         nullptr, nullptr, true);
        if (result & mtk::TEXT_INPUT_CHANGED)
            st->confirm_len = mtk::text_input_len(st->confirm, (int)sizeof(st->confirm));
    }
}

static void chpwd_on_close(Window* win) {
    if (win->app_data) {
        montauk::mfree(win->app_data);
        win->app_data = nullptr;
    }
}

void open_change_pwd_dialog(UserManagerState* parent) {
    if (parent->selected_user < 0) return;

    DesktopState* ds = parent->desktop;
    int w = 340;
    int h = 260;
    int wx = (ds->screen_w - w) / 2;
    int wy = (ds->screen_h - h) / 2;
    int idx = desktop_create_window(ds, "Change Password", wx, wy, w, h);
    if (idx < 0) return;

    Window* win = &ds->windows[idx];
    ChPwdDialogState* st = (ChPwdDialogState*)montauk::malloc(sizeof(ChPwdDialogState));
    montauk::memset(st, 0, sizeof(ChPwdDialogState));
    st->ds = ds;
    st->parent = parent;
    st->accent = ds->settings.accent_color;
    st->mouse_x = -1;
    st->mouse_y = -1;
    montauk::strncpy(st->username, parent->users[parent->selected_user].username, 31);
    montauk::strncpy(st->display_name, parent->users[parent->selected_user].display_name, 63);

    win->app_data = st;
    win->on_draw = chpwd_on_draw;
    win->on_mouse = chpwd_on_mouse;
    win->on_key = chpwd_on_key;
    win->on_close = chpwd_on_close;
}

struct DeleteUserDialogState {
    DesktopState* ds;
    UserManagerState* parent;
    char username[32];
    bool hover_delete;
    bool hover_cancel;
};

static void deluser_on_draw(Window* win, Framebuffer& fb) {
    (void)fb;
    DeleteUserDialogState* st = (DeleteUserDialogState*)win->app_data;
    if (!st) return;

    Canvas c(win);
    mtk::Theme theme = usermanager_theme(st->parent);
    c.fill(theme.window_bg);

    int sfh = system_font_height();
    char msg[96];
    snprintf(msg, sizeof(msg), "Delete user \"%s\"?", st->username);
    int tw = text_width(msg);
    c.text((c.w - tw) / 2, 24, msg, theme.text);

    const char* warn = "This action cannot be undone.";
    tw = text_width(warn);
    c.text((c.w - tw) / 2, 24 + sfh + 8, warn, theme.text_muted);

    int btn_w = 100;
    int btn_h = 32;
    int btn_y = c.h - btn_h - 20;
    int gap = 20;
    int total = btn_w * 2 + gap;
    int bx = (c.w - total) / 2;

    Rect delete_btn = {bx, btn_y, btn_w, btn_h};
    Rect cancel_btn = {bx + btn_w + gap, btn_y, btn_w, btn_h};
    mtk::draw_button(c, delete_btn, "Delete", mtk::BUTTON_DANGER,
                     mtk::widget_state(false, st->hover_delete), theme);
    mtk::draw_button(c, cancel_btn, "Cancel", mtk::BUTTON_SECONDARY,
                     mtk::widget_state(false, st->hover_cancel), theme);
}

static void deluser_on_mouse(Window* win, MouseEvent& ev) {
    DeleteUserDialogState* st = (DeleteUserDialogState*)win->app_data;
    if (!st) return;

    mtk::DesktopHost host(win);
    int mx = 0;
    int my = 0;
    if (!host.map_mouse(ev, &mx, &my)) return;

    int btn_w = 100;
    int btn_h = 32;
    int btn_y = win->content_h - btn_h - 20;
    int gap = 20;
    int total = btn_w * 2 + gap;
    int bx = (win->content_w - total) / 2;

    Rect delete_btn = {bx, btn_y, btn_w, btn_h};
    Rect cancel_btn = {bx + btn_w + gap, btn_y, btn_w, btn_h};

    bool old_delete = st->hover_delete;
    bool old_cancel = st->hover_cancel;
    st->hover_delete = delete_btn.contains(mx, my);
    st->hover_cancel = cancel_btn.contains(mx, my);
    if (old_delete != st->hover_delete || old_cancel != st->hover_cancel) {
        host.invalidate();
    }

    if (ev.left_pressed()) {
        if (st->hover_delete) {
            montauk::user::delete_user(st->username);
            st->parent->users_loaded = false;
            st->parent->selected_user = -1;
            usermanager_set_status(st->parent, "User deleted");
            dialog_close_self(st->ds, st);
            return;
        }
        if (st->hover_cancel) {
            dialog_close_self(st->ds, st);
            return;
        }
    }
}

static void deluser_on_key(Window* win, const Montauk::KeyEvent& key) {
    DeleteUserDialogState* st = (DeleteUserDialogState*)win->app_data;
    if (!st || !key.pressed) return;

    if (key.ascii == '\n' || key.ascii == '\r') {
        montauk::user::delete_user(st->username);
        st->parent->users_loaded = false;
        st->parent->selected_user = -1;
        usermanager_set_status(st->parent, "User deleted");
        dialog_close_self(st->ds, st);
    }
    if (key.scancode == 0x01) {
        dialog_close_self(st->ds, st);
    }
}

static void deluser_on_close(Window* win) {
    if (win->app_data) {
        montauk::mfree(win->app_data);
        win->app_data = nullptr;
    }
}

void open_delete_user_dialog(UserManagerState* parent) {
    if (parent->selected_user < 0) return;

    DesktopState* ds = parent->desktop;
    if (montauk::streq(parent->users[parent->selected_user].username, ds->current_user)) {
        usermanager_set_status(parent, "Cannot delete current user");
        return;
    }

    int w = 300;
    int h = 150;
    int wx = (ds->screen_w - w) / 2;
    int wy = (ds->screen_h - h) / 2;
    int idx = desktop_create_window(ds, "Delete User", wx, wy, w, h);
    if (idx < 0) return;

    Window* win = &ds->windows[idx];
    DeleteUserDialogState* st = (DeleteUserDialogState*)montauk::malloc(sizeof(DeleteUserDialogState));
    montauk::memset(st, 0, sizeof(DeleteUserDialogState));
    st->ds = ds;
    st->parent = parent;
    montauk::strncpy(st->username, parent->users[parent->selected_user].username, 31);

    win->app_data = st;
    win->on_draw = deluser_on_draw;
    win->on_mouse = deluser_on_mouse;
    win->on_key = deluser_on_key;
    win->on_close = deluser_on_close;
}

} // namespace usermanager_app
