/*
    * render.cpp
    * Drawing code for the embedded desktop file manager
    * Copyright (c) 2026 Daniel Hammer
*/

#include "filemanager_internal.hpp"

namespace filemanager {

static bool label_break_char(char ch) {
    return ch == ' ' || ch == '-' || ch == '_' || ch == '/';
}

static void copy_label_range(char* dst, int dst_max, const char* src, int start, int end) {
    if (!dst || dst_max <= 0) return;
    while (start < end && src[start] == ' ') start++;
    while (end > start && src[end - 1] == ' ') end--;

    int out = 0;
    for (int i = start; i < end && out < dst_max - 1; i++) {
        dst[out++] = src[i];
    }
    dst[out] = '\0';
}

static int fitted_prefix_len(const char* src, int max_w, int max_len) {
    char tmp[128];
    int best = 0;
    int limit = max_len < 127 ? max_len : 127;
    for (int len = 1; len <= limit; len++) {
        copy_label_range(tmp, sizeof(tmp), src, 0, len);
        if (text_width(tmp) > max_w) break;
        best = len;
    }
    return best > 0 ? best : 1;
}

static void fit_label_with_ellipsis(char* dst, int dst_max, const char* src, int max_w) {
    montauk::strncpy(dst, src, dst_max);
    if (text_width(dst) <= max_w) return;

    int ellipsis_w = text_width("...");
    int len = montauk::slen(dst);
    while (len > 0) {
        dst[len] = '\0';
        if (text_width(dst) + ellipsis_w <= max_w) break;
        len--;
    }

    if (len > dst_max - 4) len = dst_max - 4;
    if (len < 0) len = 0;
    dst[len] = '.';
    dst[len + 1] = '.';
    dst[len + 2] = '.';
    dst[len + 3] = '\0';
}

static void build_grid_label_lines(const char* name, int max_w,
                                   char* line1, int line1_max,
                                   char* line2, int line2_max) {
    line1[0] = '\0';
    line2[0] = '\0';

    if (text_width(name) <= max_w) {
        montauk::strncpy(line1, name, line1_max);
        return;
    }

    int nlen = montauk::slen(name);
    int break_end = -1;
    int break_next = -1;

    for (int i = 0; i < nlen - 1; i++) {
        if (!label_break_char(name[i])) continue;

        int end = (name[i] == ' ') ? i : i + 1;
        int next = i + 1;

        char candidate[128];
        copy_label_range(candidate, sizeof(candidate), name, 0, end);
        if (candidate[0] != '\0' && text_width(candidate) <= max_w) {
            break_end = end;
            break_next = next;
        }
    }

    if (break_end < 0) {
        break_end = fitted_prefix_len(name, max_w, nlen);
        break_next = break_end;
    }

    copy_label_range(line1, line1_max, name, 0, break_end);
    fit_label_with_ellipsis(line2, line2_max, name + break_next, max_w);
}

static void draw_centered_grid_label(Canvas& c, int cell_x, int y, const char* label, Color color) {
    int tw = text_width(label);
    int tx = cell_x + (FM_GRID_CELL_W - tw) / 2;
    if (tx < cell_x + 2) tx = cell_x + 2;
    c.text(tx, y, label, color);
}

int filemanager_grid_row_height(FileManagerState* fm, int row, int cols) {
    if (!fm || cols <= 0 || row < 0) return FM_GRID_CELL_H;

    int start = row * cols;
    int end = start + cols;
    if (end > fm->entry_count) end = fm->entry_count;

    int max_w = FM_GRID_CELL_W - 4;
    for (int i = start; i < end; i++) {
        if (text_width(fm->entry_names[i]) > max_w) {
            return FM_GRID_CELL_H_WRAPPED;
        }
    }

    return FM_GRID_CELL_H;
}

int filemanager_grid_row_y(FileManagerState* fm, int row, int cols) {
    int y = 0;
    for (int r = 0; r < row; r++) {
        y += filemanager_grid_row_height(fm, r, cols);
    }
    return y;
}

int filemanager_grid_content_height(FileManagerState* fm, int cols) {
    if (!fm || cols <= 0) return 0;

    int rows = (fm->entry_count + cols - 1) / cols;
    int h = 0;
    for (int r = 0; r < rows; r++) {
        h += filemanager_grid_row_height(fm, r, cols);
    }
    return h;
}

int filemanager_grid_index_at(FileManagerState* fm, int cols, int x, int rel_y) {
    if (!fm || cols <= 0 || x < 0 || rel_y < 0) return -1;

    int col = x / FM_GRID_CELL_W;
    if (col < 0 || col >= cols) return -1;

    int rows = (fm->entry_count + cols - 1) / cols;
    int row_y = 0;
    for (int row = 0; row < rows; row++) {
        int row_h = filemanager_grid_row_height(fm, row, cols);
        if (rel_y < row_y + row_h) {
            int idx = row * cols + col;
            return idx < fm->entry_count ? idx : -1;
        }
        row_y += row_h;
    }

    return -1;
}

void filemanager_draw_header(Canvas& c, FileManagerState* fm, Color toolbar_color, Color btn_bg) {
    DesktopState* ds = fm->desktop;

    // ---- Toolbar (32px) ----
    c.fill_rect(0, 0, c.w, FM_TOOLBAR_H, toolbar_color);

    // Navigation buttons: Back, Forward, Up, Home
    struct ToolBtn { int x; SvgIcon* icon; };
    ToolBtn nav_btns[4] = {
        {  4, ds ? &ds->icon_go_back    : nullptr },
        { 32, ds ? &ds->icon_go_forward : nullptr },
        { 60, ds ? &ds->icon_go_up      : nullptr },
        { 88, ds ? &ds->icon_home       : nullptr },
    };

    for (int i = 0; i < 4; i++) {
        int bx = nav_btns[i].x;
        int by = 4;
        c.fill_rect(bx, by, 24, 24, btn_bg);
        if (nav_btns[i].icon) {
            int ix = bx + (24 - nav_btns[i].icon->width) / 2;
            int iy = by + (24 - nav_btns[i].icon->height) / 2;
            c.icon(ix, iy, *nav_btns[i].icon);
        }
    }

    // View toggle button
    {
        int bx = 120, by = 4;
        c.fill_rect(bx, by, 24, 24, btn_bg);
        if (fm->grid_view) {
            for (int r = 0; r < 2; r++)
                for (int cc = 0; cc < 2; cc++)
                    c.fill_rect(bx + 5 + cc * 8, by + 5 + r * 8, 6, 6, colors::TEXT_COLOR);
        } else {
            for (int r = 0; r < 3; r++)
                c.fill_rect(bx + 5, by + 5 + r * 5, 14, 2, colors::TEXT_COLOR);
        }
    }

    // Separator line between nav group and action group
    c.vline(152, 6, 20, colors::BORDER);

    // Action buttons: Copy, Cut, Paste, Rename, New Folder, Delete
    bool has_sel = fm->selected >= 0 && fm->selected < fm->entry_count
                   && !filemanager_is_computer_view(fm) && !filemanager_is_virtual_view(fm)
                   && fm->entry_types[fm->selected] != FM_ENTRY_DRIVE;
    bool has_clip = fm->clipboard_has_data && !filemanager_is_computer_view(fm)
                    && !filemanager_is_virtual_view(fm);
    Color dim_bg = Color::from_rgb(0xF0, 0xF0, 0xF0);

    // Icon toolbar buttons: Copy, Cut, Paste, Rename, New Folder, Delete
    struct ActionBtn { int x; SvgIcon* icon; bool enabled; };
    ActionBtn action_btns[] = {
        { 160, ds ? &ds->icon_copy       : nullptr, has_sel },
        { 188, ds ? &ds->icon_cut        : nullptr, has_sel },
        { 216, ds ? &ds->icon_paste      : nullptr, has_clip },
        { 244, ds ? &ds->icon_rename     : nullptr, has_sel },
        { 272, ds ? &ds->icon_folder_new : nullptr,
          !filemanager_is_computer_view(fm) && !filemanager_is_virtual_view(fm) },
        { 300, ds ? &ds->icon_delete     : nullptr, has_sel },
    };

    for (int i = 0; i < 6; i++) {
        int bx = action_btns[i].x;
        int by = 4;
        c.fill_rect(bx, by, 24, 24, action_btns[i].enabled ? btn_bg : dim_bg);
        if (action_btns[i].icon && action_btns[i].icon->pixels) {
            int ix = bx + (24 - action_btns[i].icon->width) / 2;
            int iy = by + (24 - action_btns[i].icon->height) / 2;
            c.icon(ix, iy, *action_btns[i].icon);
        }
    }

    // Toolbar separator
    c.hline(0, FM_TOOLBAR_H - 1, c.w, colors::BORDER);

    // ---- Path bar ----
    int pathbar_y = FM_TOOLBAR_H;
    if (fm->pathbar_editing) {
        // Editable text input
        c.fill_rect(0, pathbar_y, c.w, FM_PATHBAR_H, colors::WHITE);
        c.rect(0, pathbar_y, c.w, FM_PATHBAR_H, colors::ACCENT);
        int fh = system_font_height();
        int ty = pathbar_y + (FM_PATHBAR_H - fh) / 2;
        c.text(8, ty, fm->pathbar_buf, colors::TEXT_COLOR);
        // Cursor
        char prefix[256];
        int cpos = fm->pathbar_cursor;
        if (cpos > 255) cpos = 255;
        for (int k = 0; k < cpos; k++) prefix[k] = fm->pathbar_buf[k];
        prefix[cpos] = '\0';
        int cx = 8 + text_width(prefix);
        c.vline(cx, ty, fh, colors::ACCENT);
    } else {
        c.fill_rect(0, pathbar_y, c.w, FM_PATHBAR_H, Color::from_rgb(0xF0, 0xF0, 0xF0));
        const char* pathbar_text = fm->current_path;
        if (filemanager_is_computer_view(fm)) pathbar_text = "Computer";
        else if (filemanager_is_virtual_view(fm)) pathbar_text = filemanager_virtual_view_label(fm->virtual_view);
        c.text(8, pathbar_y + 4, pathbar_text, colors::TEXT_COLOR);
    }

    // Path bar separator
    c.hline(0, pathbar_y + FM_PATHBAR_H - 1, c.w, colors::BORDER);
}

void filemanager_on_draw(Window* win, Framebuffer& fb) {
    FileManagerState* fm = (FileManagerState*)win->app_data;
    if (!fm) return;

    Canvas c(win);
    c.fill(colors::WINDOW_BG);

    Color toolbar_color = Color::from_rgb(0xF5, 0xF5, 0xF5);
    Color btn_bg = Color::from_rgb(0xE8, 0xE8, 0xE8);
    Color dim = Color::from_rgb(0x88, 0x88, 0x88);
    DesktopState* ds = fm->desktop;

    // Draw header (toolbar + path bar)
    filemanager_draw_header(c, fm, toolbar_color, btn_bg);

    if (fm->grid_view) {
        // ---- Grid View ----
        int list_y = FM_TOOLBAR_H + FM_PATHBAR_H;
        int list_h = c.h - list_y;
        int cols = (c.w - FM_SCROLLBAR_W) / FM_GRID_CELL_W;
        if (cols < 1) cols = 1;
        int content_h = filemanager_grid_content_height(fm, cols);

        // Update scrollbar
        fm->scrollbar.bounds = {c.w - FM_SCROLLBAR_W, list_y, FM_SCROLLBAR_W, list_h};
        fm->scrollbar.content_height = content_h;
        fm->scrollbar.view_height = list_h;

        for (int i = 0; i < fm->entry_count; i++) {
            int col = i % cols;
            int row = i / cols;
            int cell_x = col * FM_GRID_CELL_W;
            int row_h = filemanager_grid_row_height(fm, row, cols);
            int cell_y = list_y + filemanager_grid_row_y(fm, row, cols) - fm->scrollbar.scroll_offset;

            // Skip if entirely off-screen
            if (cell_y + row_h <= list_y || cell_y >= c.h) continue;

            // Selection highlight
            if (i == fm->selected) {
                int sy = gui_max(cell_y, list_y);
                int sh = gui_min(cell_y + row_h, c.h) - sy;
                int sw = gui_min(FM_GRID_CELL_W, c.w - FM_SCROLLBAR_W - cell_x);
                if (sh > 0 && sw > 0)
                    c.fill_rect(cell_x, sy, sw, sh, colors::MENU_HOVER);
            }

            // Large icon centered horizontally
            int icon_x = cell_x + (FM_GRID_CELL_W - FM_GRID_ICON) / 2;
            int icon_y = cell_y + FM_GRID_PAD;
            // Check for special folder icon (type 7 in Computer, or type 1 dir with matching name)
            int sfi = -1;
            if (fm->entry_types[i] == FM_ENTRY_SPECIAL_DIR) sfi = fm->drive_indices[i];
            else if (ds && fm->entry_types[i] == FM_ENTRY_DIR) sfi = special_folder_index(fm->entry_names[i]);

            if (sfi >= 0 && ds && ds->icon_special_folder_lg[sfi].pixels) {
                c.icon(icon_x, icon_y, ds->icon_special_folder_lg[sfi]);
            } else if (fm->entry_types[i] == FM_ENTRY_VIRTUAL_APP
                       && i < fm->virtual_entry_count
                       && fm->virtual_entries[i].icon_lg.pixels) {
                c.icon(icon_x, icon_y, fm->virtual_entries[i].icon_lg);
            } else if (ds && fm->entry_types[i] == FM_ENTRY_SYSTEM_CONFIGURATION_ROOT
                       && ds->icon_system_configuration_lg.pixels) {
                c.icon(icon_x, icon_y, ds->icon_system_configuration_lg);
            } else if (ds && fm->entry_types[i] == FM_ENTRY_APPS_ROOT && ds->icon_apps_lg.pixels) {
                c.icon(icon_x, icon_y, ds->icon_apps_lg);
            } else if (ds && fm->entry_types[i] == FM_ENTRY_HOME && ds->icon_home_folder_lg.pixels) {
                c.icon(icon_x, icon_y, ds->icon_home_folder_lg);
            } else if (ds && fm->entry_types[i] == FM_ENTRY_DRIVE && ds->icon_drive_lg.pixels) {
                c.icon(icon_x, icon_y, ds->icon_drive_lg);
            } else if (ds && fm->entry_types[i] == FM_ENTRY_DIR && ds->icon_folder_lg.pixels) {
                c.icon(icon_x, icon_y, ds->icon_folder_lg);
            } else if (ds && fm->entry_types[i] == FM_ENTRY_EXEC && ds->icon_exec_lg.pixels) {
                c.icon(icon_x, icon_y, ds->icon_exec_lg);
            } else if (ds && ds->icon_file_lg.pixels) {
                c.icon(icon_x, icon_y, ds->icon_file_lg);
            } else {
                Color icon_c = fm->is_dir[i]
                    ? Color::from_rgb(0xFF, 0xBD, 0x2E)
                    : Color::from_rgb(0x90, 0x90, 0x90);
                int iy_clip = gui_max(icon_y, list_y);
                int ih_clip = FM_GRID_ICON - (iy_clip - icon_y);
                if (ih_clip > 0)
                    c.fill_rect(icon_x, iy_clip, FM_GRID_ICON, ih_clip, icon_c);
            }

            // Filename centered below icon, truncated if needed
            // If renaming this entry, draw the rename textbox instead
            if (fm->rename_active && fm->rename_idx == i) {
                int ty = icon_y + FM_GRID_ICON + 2;
                int tw = FM_GRID_CELL_W - 4;
                if (ty >= list_y && ty + system_font_height() + 4 <= c.h) {
                    c.fill_rect(cell_x + 2, ty - 1, tw, system_font_height() + 2, colors::WHITE);
                    c.rect(cell_x + 2, ty - 1, tw, system_font_height() + 2, colors::ACCENT);
                    // Draw rename text (truncated to cell width)
                    char display[16];
                    int rlen = fm->rename_len;
                    if (rlen > 10) rlen = 10;
                    for (int k = 0; k < rlen; k++) display[k] = fm->rename_buf[k];
                    display[rlen] = '\0';
                    c.text(cell_x + 4, ty, display, colors::TEXT_COLOR);
                    // Cursor
                    char prefix[64];
                    int cpos = fm->rename_cursor < rlen ? fm->rename_cursor : rlen;
                    for (int k = 0; k < cpos; k++) prefix[k] = fm->rename_buf[k];
                    prefix[cpos] = '\0';
                    int cx = cell_x + 4 + text_width(prefix);
                    c.vline(cx, ty, system_font_height(), colors::ACCENT);
                }
            } else {
                // Prefer two grid label rows before truncating.
                int max_w = FM_GRID_CELL_W - 4;
                const char* name = fm->entry_names[i];
                char line1[128];
                char line2[128];
                build_grid_label_lines(name, max_w, line1, sizeof(line1), line2, sizeof(line2));

                int ty = icon_y + FM_GRID_ICON + 2;
                int fh = system_font_height();
                if (ty >= list_y && ty + fh <= c.h) {
                    draw_centered_grid_label(c, cell_x, ty, line1, colors::TEXT_COLOR);
                }
                if (line2[0] != '\0' && ty + fh >= list_y && ty + fh * 2 <= c.h) {
                    draw_centered_grid_label(c, cell_x, ty + fh, line2, colors::TEXT_COLOR);
                }
            }
        }
    } else {
        // ---- List View ----

        // ---- Column headers ----
        int header_y = FM_TOOLBAR_H + FM_PATHBAR_H;
        c.fill_rect(0, header_y, c.w, FM_HEADER_H, Color::from_rgb(0xF8, 0xF8, 0xF8));

        int name_col_x = 8;
        int size_col_x = c.w - FM_SCROLLBAR_W - 120;
        int type_col_x = c.w - FM_SCROLLBAR_W - 60;

        c.text(name_col_x, header_y + 2, "Name", dim);
        if (size_col_x > 100)
            c.text(size_col_x, header_y + 2, "Size", dim);
        if (type_col_x > 160)
            c.text(type_col_x, header_y + 2, "Type", dim);

        // Header separator
        c.hline(0, header_y + FM_HEADER_H - 1, c.w, colors::BORDER);

        // Column separator lines
        if (size_col_x > 100) {
            c.vline(size_col_x - 4, header_y, c.h - header_y, colors::BORDER);
        }

        // ---- File entries ----
        int list_y = header_y + FM_HEADER_H;
        int list_h = c.h - list_y;
        int visible_items = list_h / FM_ITEM_H;
        int content_h = fm->entry_count * FM_ITEM_H;

        // Update scrollbar
        fm->scrollbar.bounds = {c.w - FM_SCROLLBAR_W, list_y, FM_SCROLLBAR_W, list_h};
        fm->scrollbar.content_height = content_h;
        fm->scrollbar.view_height = list_h;

        int scroll_items = fm->scrollbar.scroll_offset / FM_ITEM_H;

        for (int i = scroll_items; i < fm->entry_count && (i - scroll_items) < visible_items + 1; i++) {
            int iy = list_y + (i - scroll_items) * FM_ITEM_H - (fm->scrollbar.scroll_offset % FM_ITEM_H);
            if (iy + FM_ITEM_H <= list_y || iy >= c.h) continue;

            // Highlight selected
            if (i == fm->selected) {
                int sy = gui_max(iy, list_y);
                int sh = gui_min(iy + FM_ITEM_H, c.h) - sy;
                if (sh > 0)
                    c.fill_rect(0, sy, c.w - FM_SCROLLBAR_W, sh, colors::MENU_HOVER);
            }

            // Icon (skip if it would bleed above the list area)
            int ico_x = 8;
            int ico_y = iy + (FM_ITEM_H - 16) / 2;
            // Check for special folder icon
            int sfi_sm = -1;
            if (fm->entry_types[i] == FM_ENTRY_SPECIAL_DIR) sfi_sm = fm->drive_indices[i];
            else if (ds && fm->entry_types[i] == FM_ENTRY_DIR) sfi_sm = special_folder_index(fm->entry_names[i]);

            if (ico_y < list_y) { /* clipped by header repaint */ }
            else if (sfi_sm >= 0 && ds && ds->icon_special_folder[sfi_sm].pixels) {
                c.icon(ico_x, ico_y, ds->icon_special_folder[sfi_sm]);
            } else if (fm->entry_types[i] == FM_ENTRY_VIRTUAL_APP
                       && i < fm->virtual_entry_count
                       && fm->virtual_entries[i].icon_sm.pixels) {
                c.icon(ico_x, ico_y, fm->virtual_entries[i].icon_sm);
            } else if (ds && fm->entry_types[i] == FM_ENTRY_SYSTEM_CONFIGURATION_ROOT
                       && ds->icon_system_configuration.pixels) {
                c.icon(ico_x, ico_y, ds->icon_system_configuration);
            } else if (ds && fm->entry_types[i] == FM_ENTRY_APPS_ROOT && ds->icon_apps.pixels) {
                c.icon(ico_x, ico_y, ds->icon_apps);
            } else if (ds && fm->entry_types[i] == FM_ENTRY_HOME && ds->icon_home_folder.pixels) {
                c.icon(ico_x, ico_y, ds->icon_home_folder);
            } else if (ds && fm->entry_types[i] == FM_ENTRY_DRIVE && ds->icon_drive.pixels) {
                c.icon(ico_x, ico_y, ds->icon_drive);
            } else if (ds && fm->entry_types[i] == FM_ENTRY_DIR && ds->icon_folder.pixels) {
                c.icon(ico_x, ico_y, ds->icon_folder);
            } else if (ds && fm->entry_types[i] == FM_ENTRY_EXEC && ds->icon_exec.pixels) {
                c.icon(ico_x, ico_y, ds->icon_exec);
            } else if (ds && ds->icon_file.pixels) {
                c.icon(ico_x, ico_y, ds->icon_file);
            } else {
                Color icon_c = fm->is_dir[i]
                    ? Color::from_rgb(0xFF, 0xBD, 0x2E)
                    : Color::from_rgb(0x90, 0x90, 0x90);
                int iy_clip = gui_max(ico_y, list_y);
                int ih_clip = 16 - (iy_clip - ico_y);
                if (ih_clip > 0)
                    c.fill_rect(ico_x, iy_clip, 16, ih_clip, icon_c);
            }

            // Name (or rename textbox)
            int tx = 30;
            int fm_sfh = system_font_height();
            int ty = iy + (FM_ITEM_H - fm_sfh) / 2;

            if (fm->rename_active && fm->rename_idx == i && ty >= list_y && ty + fm_sfh <= c.h) {
                // Rename textbox inline
                int rw = (size_col_x > 100 ? size_col_x - 8 : c.w - FM_SCROLLBAR_W - 8) - tx;
                c.fill_rect(tx - 2, ty - 1, rw, fm_sfh + 2, colors::WHITE);
                c.rect(tx - 2, ty - 1, rw, fm_sfh + 2, colors::ACCENT);
                c.text(tx, ty, fm->rename_buf, colors::TEXT_COLOR);
                // Cursor
                char prefix[64];
                int cpos = fm->rename_cursor;
                if (cpos > 63) cpos = 63;
                for (int k = 0; k < cpos; k++) prefix[k] = fm->rename_buf[k];
                prefix[cpos] = '\0';
                int cx = tx + text_width(prefix);
                c.vline(cx, ty, fm_sfh, colors::ACCENT);
            } else {
                if (ty >= list_y && ty + fm_sfh <= c.h) {
                    // Truncate name to fit the name column width
                    const char* name = fm->entry_names[i];
                    int name_max_w = size_col_x - tx - 8;
                    if (name_max_w < 20) name_max_w = c.w - FM_SCROLLBAR_W - tx - 8;
                    char label[64];
                    montauk::strncpy(label, name, 63);

                    if (text_width(label) > name_max_w && montauk::slen(name) > 3) {
                        int ellipsis_w = text_width("...");
                        int final_len = montauk::slen(name);
                        while (final_len > 1) {
                            label[final_len] = '\0';
                            int w = text_width(label);
                            if (w + ellipsis_w <= name_max_w) break;
                            final_len--;
                        }
                        if (final_len > 60) final_len = 60;
                        label[final_len] = '.';
                        label[final_len + 1] = '.';
                        label[final_len + 2] = '.';
                        label[final_len + 3] = '\0';
                    }
                    c.text(tx, ty, label, colors::TEXT_COLOR);
                }
            }

            // Size
            if (size_col_x > 100 && !fm->is_dir[i] && ty >= list_y && ty + fm_sfh <= c.h) {
                char size_str[16];
                format_size(size_str, fm->entry_sizes[i]);
                c.text(size_col_x, ty, size_str, dim);
            }

            // Type
            if (type_col_x > 160 && ty >= list_y && ty + fm_sfh <= c.h) {
                const char* type_str = "File";
                if (fm->entry_types[i] == FM_ENTRY_VIRTUAL_APP) {
                    type_str = fm->virtual_view == FM_VIRTUAL_VIEW_SYSTEM_CONFIGURATION
                        ? "Applet"
                        : "App";
                }
                else if (fm->entry_types[i] == FM_ENTRY_APPS_ROOT) type_str = "Apps";
                else if (fm->entry_types[i] == FM_ENTRY_SYSTEM_CONFIGURATION_ROOT) type_str = "System";
                else if (fm->entry_types[i] == FM_ENTRY_HOME) type_str = "Home";
                else if (fm->entry_types[i] == FM_ENTRY_DRIVE) type_str = "Drive";
                else if (fm->entry_types[i] == FM_ENTRY_DIR) type_str = "Dir";
                else if (fm->entry_types[i] == FM_ENTRY_EXEC) type_str = "Exec";
                c.text(type_col_x, ty, type_str, dim);
            }
        }
    }

    // ---- Scrollbar ----
    if (fm->scrollbar.content_height > fm->scrollbar.view_height) {
        Color sb_fg_color = (fm->scrollbar.hovered || fm->scrollbar.dragging)
            ? fm->scrollbar.hover_fg : fm->scrollbar.fg;

        int sbx = fm->scrollbar.bounds.x;
        int sby = fm->scrollbar.bounds.y;
        int sbw = fm->scrollbar.bounds.w;
        int sbh = fm->scrollbar.bounds.h;

        c.fill_rect(sbx, sby, sbw, sbh, colors::SCROLLBAR_BG);

        int th = fm->scrollbar.thumb_height();
        int tty = fm->scrollbar.thumb_y();
        c.fill_rect(sbx + 1, tty, sbw - 2, th, sb_fg_color);
    }

    // Repaint header on top of content to clip scrolled icon overflow
    if (fm->scrollbar.scroll_offset > 0)
        filemanager_draw_header(c, fm, toolbar_color, btn_bg);

    // ---- Context menu overlay ----
    if (fm->ctx_open && fm->ctx_item_count > 0) {
        mtk::Theme theme = mtk::make_theme(colors::ACCENT);
        theme.border = colors::BORDER;
        theme.text = colors::TEXT_COLOR;

        mtk::ContextMenuItem items[8];
        filemanager_build_context_items(fm, items, 8);
        mtk::draw_context_menu(c, filemanager_context_state(fm), items,
                               fm->ctx_item_count, theme);
    }
}

} // namespace filemanager
