
using MenuGenerator.Models;
using System;
using System.Collections.Generic;
using System.Text;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TextBox;

namespace MenuGenerator.Generators
{
    public static class MenuCodeGenerator
    {
        // ----------------------------------------------------------------
        // Вспомогательный метод: обходим дерево и строим плоский список
        // с заполнением Parent, FirstChild, LastChild
        
        // ----------------------------------------------------------------
        public static List<MenuNode> Flatten(MenuNode root)
        {
            var list = new List<MenuNode>();
            // Корень (индекс 0) — сам root (папка верхнего уровня)
            list.Add(root);
            FlattenChildren(root, 0, list);
            return list;
        }

        private static void FlattenChildren(MenuNode node, int parentIndex, List<MenuNode> list)
        {
            if (node.Children == null || node.Children.Count == 0)
                return;

            int firstIdx = list.Count;
            // Сначала добавляем всех прямых детей
            foreach (var child in node.Children)
            {
                child.Parent = parentIndex;
                list.Add(child);
            }
            int lastIdx = list.Count - 1;

            // Обновляем родителя
            list[parentIndex].FirstChild = firstIdx;
            list[parentIndex].LastChild = lastIdx;

            // Рекурсия для каждого ребёнка
            for (int i = firstIdx; i <= lastIdx; i++)
            {
                FlattenChildren(list[i], i, list);
            }
        }

        // ----------------------------------------------------------------
        // Генерация menu.h
        // ----------------------------------------------------------------
        public static string GenerateH(
            MenuNode root,
            string menuName,
            int displayLines,
            string mcuType,
            string lcdType,
            string controlType)
        {
            var flat = Flatten(root);
            int count = flat.Count;
            var sb = new StringBuilder();

            sb.AppendLine($"// Файл {menuName}.h");
            sb.AppendLine($"// Сгенерировано MenuGenerator");
            sb.AppendLine($"// MCU: {mcuType}  LCD: {lcdType}  Управление: {controlType}");
            sb.AppendLine();
            string guard = menuName.ToUpper().Replace(" ", "_") + "_H";
            sb.AppendLine($"#ifndef {guard}");
            sb.AppendLine($"#define {guard}");
            sb.AppendLine();

            // Includes по типу MCU
            if (mcuType.StartsWith("STM32"))
                sb.AppendLine("#include \"stm32f4xx_hal.h\"");
            else
                sb.AppendLine("#include <avr/io.h>");

            sb.AppendLine("#include \"ST7735_Defines.h\"");
            sb.AppendLine("#include \"fonts.h\"");
            sb.AppendLine("#include <stdbool.h>");
            sb.AppendLine();

            sb.AppendLine("// Конфигурация меню");
            sb.AppendLine($"#define MENU_MAX_ITEMS          {count}");
            sb.AppendLine($"#define MENU_DISPLAY_LINES      {displayLines}");
            sb.AppendLine("#define MENU_LINE_HEIGHT        20");
            sb.AppendLine("#define MENU_TEXT_X_OFFSET      5");
            sb.AppendLine("#define MENU_TEXT_Y_OFFSET      2");
            sb.AppendLine();

            sb.AppendLine("// Цвета меню");
            sb.AppendLine("#define MENU_BG_COLOR               ST7735_BLACK");
            sb.AppendLine("#define MENU_TEXT_COLOR             ST7735_WHITE");
            sb.AppendLine("#define MENU_SELECTED_BG_COLOR      ST7735_DARKGREY");
            sb.AppendLine("#define MENU_SELECTED_TEXT_COLOR    ST7735_WHITE");
            sb.AppendLine("#define MENU_ICON_COLOR             ST7735_ORANGE");
            sb.AppendLine("#define MENU_SELECTED_ICON_COLOR    ST7735_ORANGE");
            sb.AppendLine("#define MENU_VALUE_COLOR            ST7735_YELLOW");
            sb.AppendLine("#define MENU_EDIT_COLOR             ST7735_CYAN");
            sb.AppendLine("#define MENU_TITLE_COLOR            ST7735_GREEN");
            sb.AppendLine("#define MENU_SCROLLBAR_COLOR        ST7735_OLIVE");
            sb.AppendLine("#define MENU_SCROLLBAR_BG_COLOR     ST7735_LIGHTGREY");
            sb.AppendLine("#define MENU_MODE_ED_COLOR          ST7735_RED");
            sb.AppendLine("#define MENU_TEXT_ED_COLOR          ST7735_GREENYELLOW");
            sb.AppendLine();

            sb.AppendLine("// Типы элементов меню");
            sb.AppendLine("typedef enum {");
            sb.AppendLine("    MENU_TYPE_FOLDER = 0,");
            sb.AppendLine("    MENU_TYPE_INTEGER,");
            sb.AppendLine("    MENU_TYPE_BOOLEAN,");
            sb.AppendLine("    MENU_TYPE_TEMPERATURE,");
            sb.AppendLine("    MENU_TYPE_TEMPERATURE_HIGH,");
            sb.AppendLine("    MENU_TYPE_PERCENTAGE,");
            sb.AppendLine("    MENU_TYPE_YEAR,");
            sb.AppendLine("    MENU_TYPE_MONTH,");
            sb.AppendLine("    MENU_TYPE_DAY,");
            sb.AppendLine("    MENU_TYPE_HOUR,");
            sb.AppendLine("    MENU_TYPE_MINUTE,");
            sb.AppendLine("    MENU_TYPE_ACTION,");
            sb.AppendLine("    MENU_TYPE_INFO");
            sb.AppendLine("} MenuItemType;");
            sb.AppendLine();

            sb.AppendLine("// Режимы работы меню");
            sb.AppendLine("typedef enum {");
            sb.AppendLine("    MENU_MODE_NONE = 0,");
            sb.AppendLine("    MENU_MODE_BROWSE,");
            sb.AppendLine("    MENU_MODE_EDIT,");
            sb.AppendLine("    MENU_MODE_QUICK");
            sb.AppendLine("} MenuMode;");
            sb.AppendLine();

            sb.AppendLine("// Структура элемента меню");
            sb.AppendLine("typedef struct {");
            sb.AppendLine("    const char* name;");
            sb.AppendLine("    MenuItemType type;");
            sb.AppendLine("    uint8_t parent;");
            sb.AppendLine("    uint8_t first_child;");
            sb.AppendLine("    uint8_t last_child;");
            sb.AppendLine("    uint16_t value;");
            sb.AppendLine("    uint16_t min_value;");
            sb.AppendLine("    uint16_t max_value;");
            sb.AppendLine("    uint8_t step;");
            sb.AppendLine("} MenuItemDef;");
            sb.AppendLine();

            sb.AppendLine("// Состояние меню");
            sb.AppendLine("typedef struct {");
            sb.AppendLine("    uint8_t current_item;");
            sb.AppendLine("    uint8_t display_start;");
            sb.AppendLine("    uint8_t selected_line;");
            sb.AppendLine("    MenuMode mode;");
            sb.AppendLine("    bool needs_redraw;");
            sb.AppendLine("    bool value_changed;");
            sb.AppendLine($"    uint8_t prev_display_ids[MENU_DISPLAY_LINES];");
            sb.AppendLine("    uint8_t prev_selected_line;");
            sb.AppendLine("    MenuMode prev_mode;");
            sb.AppendLine("    uint8_t prev_parent;");
            sb.AppendLine("} MenuState;");
            sb.AppendLine();

            sb.AppendLine("typedef void (*MenuSaveCallback)(void);");
            sb.AppendLine("typedef void (*MenuTimeCallback)(void);");
            sb.AppendLine();

            sb.AppendLine("void Menu_Init(void);");
            sb.AppendLine("void Menu_Show(void);");
            sb.AppendLine("void Menu_Hide(void);");
            sb.AppendLine("void Menu_Update(void);");
            sb.AppendLine("bool Menu_NavigateUp(void);");
            sb.AppendLine("bool Menu_NavigateDown(void);");
            sb.AppendLine("bool Menu_NavigateLeft(void);");
            sb.AppendLine("bool Menu_NavigateRight(void);");
            sb.AppendLine("bool Menu_BackOrHide(void);");
            sb.AppendLine("void Menu_SetSaveCallback(MenuSaveCallback callback);");
            sb.AppendLine("void Menu_SetTimeCallback(MenuTimeCallback callback);");
            sb.AppendLine("uint16_t Menu_GetValue(uint8_t item_id);");
            sb.AppendLine("void Menu_SetValue(uint8_t item_id, uint16_t value);");
            sb.AppendLine("bool Menu_IsVisible(void);");
            sb.AppendLine("MenuMode Menu_GetMode(void);");
            sb.AppendLine("void Menu_DrawScrollbar(uint8_t total_items);");
            sb.AppendLine("void Menu_ResetSettings(void);");
            sb.AppendLine("void Menu_ResetWiFi(void);");
            sb.AppendLine();

            sb.AppendLine($"#endif // {guard}");
            return sb.ToString();
        }

        // ----------------------------------------------------------------
        // Генерация menu.c
        // ----------------------------------------------------------------
        public static string GenerateC(MenuNode root, string menuName, int displayLines)
        {
            var flat = Flatten(root);
            int count = flat.Count;
            var sb = new StringBuilder();
            string hName = menuName.ToLower().Replace(" ", "_");

            sb.AppendLine($"// Файл {hName}.c");
            sb.AppendLine($"// Сгенерировано MenuGenerator");
            sb.AppendLine();
            sb.AppendLine($"#include \"{hName}.h\"");
            sb.AppendLine("#include <string.h>");
            sb.AppendLine("#include <stdio.h>");
            sb.AppendLine("#include \"drv_st7735.h\"");
            sb.AppendLine("#include \"ST7735_Defines.h\"");
            sb.AppendLine("#include \"screen_st7735.h\"");

            sb.AppendLine("#include \"sound_driver.h\"");
            sb.AppendLine("#include \"app_screens.h\"");
            sb.AppendLine();

            sb.AppendLine("static MenuState menu_state;");
            sb.AppendLine("static MenuSaveCallback save_callback = NULL;");
            sb.AppendLine("static MenuTimeCallback time_callback = NULL;");
            sb.AppendLine();

            // Генерация массива menu_items
            sb.AppendLine($"static MenuItemDef menu_items[MENU_MAX_ITEMS] = {{");
            for (int i = 0; i < flat.Count; i++)
            {
                var item = flat[i];
                string typeName = "MENU_TYPE_" + item.Type.ToString().ToUpper();
                sb.AppendLine($"    {{\"{item.Name}\", {typeName}, " +
                              $"{item.Parent}, {item.FirstChild}, {item.LastChild}, " +
                              $"{item.Value}, {item.MinValue}, {item.MaxValue}, {item.Step}}}" +
                              (i < flat.Count - 1 ? "," : ""));
            }
            sb.AppendLine("};");
            sb.AppendLine();

            // Прототипы статических функций
            sb.AppendLine("static void Menu_DrawItemLine(uint8_t line, uint8_t item_id, bool selected);");
            sb.AppendLine("static void Menu_FormatValue(uint8_t item_id, char* buffer, size_t buffer_size);");
            sb.AppendLine("static bool Menu_HasChildren(uint8_t item_id);");
            sb.AppendLine("static void Menu_UpdateDisplayRange(void);");
            sb.AppendLine();

            // Menu_Init
            sb.AppendLine("void Menu_Init(void) {");
            sb.AppendLine("    memset(&menu_state, 0, sizeof(menu_state));");
            sb.AppendLine("    menu_state.current_item     = 1;");
            sb.AppendLine("    menu_state.display_start    = 1;");
            sb.AppendLine("    menu_state.selected_line    = 0;");
            sb.AppendLine("    menu_state.mode             = MENU_MODE_NONE;");
            sb.AppendLine("    menu_state.needs_redraw     = false;");
            sb.AppendLine("    menu_state.value_changed    = false;");
            sb.AppendLine("    menu_state.prev_selected_line = 0xFF;");
            sb.AppendLine("    menu_state.prev_mode        = MENU_MODE_NONE;");
            sb.AppendLine("    menu_state.prev_parent      = 0xFF;");
            sb.AppendLine($"    for (int i = 0; i < MENU_DISPLAY_LINES; i++)");
            sb.AppendLine("        menu_state.prev_display_ids[i] = 0xFF;");
            sb.AppendLine("}");
            sb.AppendLine();

            // Menu_Show
            sb.AppendLine("void Menu_Show(void) {");
            sb.AppendLine("    menu_state.mode = MENU_MODE_BROWSE;");
            sb.AppendLine("    ST7735_FillScreen(ST7735_BLACK);");
            sb.AppendLine("    Menu_UpdateDisplayRange();");
            sb.AppendLine("    menu_state.needs_redraw = true;");
            sb.AppendLine("    Menu_Update();");
            sb.AppendLine("}");
            sb.AppendLine();

            // Menu_Hide
            sb.AppendLine("void Menu_Hide(void) {");
            sb.AppendLine("    menu_state.mode = MENU_MODE_NONE;");
            sb.AppendLine("}");
            sb.AppendLine();

            // Menu_BackOrHide
            sb.AppendLine("bool Menu_BackOrHide(void) {");
            sb.AppendLine("    if (menu_state.mode == MENU_MODE_NONE) {");
            sb.AppendLine("        Menu_Show();");
            sb.AppendLine("        return true;");
            sb.AppendLine("    }");
            sb.AppendLine("    if (menu_state.mode == MENU_MODE_EDIT) {");
            sb.AppendLine("        menu_state.mode          = MENU_MODE_BROWSE;");
            sb.AppendLine("        menu_state.value_changed = false;");
            sb.AppendLine("        menu_state.prev_mode     = MENU_MODE_NONE;");
            sb.AppendLine("        for (int i = 0; i < MENU_DISPLAY_LINES; i++)");
            sb.AppendLine("            menu_state.prev_display_ids[i] = 0xFF;");
            sb.AppendLine("        menu_state.needs_redraw = true;");
            sb.AppendLine("        return true;");
            sb.AppendLine("    }");
            sb.AppendLine("    if (menu_state.mode == MENU_MODE_BROWSE) {");
            sb.AppendLine("        uint8_t parent = menu_items[menu_state.current_item].parent;");
            sb.AppendLine("        if (parent == 0) {");
            sb.AppendLine("            Menu_Hide();");
            sb.AppendLine("            return true;");
            sb.AppendLine("        } else {");
            sb.AppendLine("            menu_state.current_item = parent;");
            sb.AppendLine("            Menu_UpdateDisplayRange();");
            sb.AppendLine("            menu_state.prev_mode = MENU_MODE_NONE;");
            sb.AppendLine("            for (int i = 0; i < MENU_DISPLAY_LINES; i++)");
            sb.AppendLine("                menu_state.prev_display_ids[i] = 0xFF;");
            sb.AppendLine("            menu_state.needs_redraw = true;");
            sb.AppendLine("            return true;");
            sb.AppendLine("        }");
            sb.AppendLine("    }");
            sb.AppendLine("    return false;");
            sb.AppendLine("}");
            sb.AppendLine();

            // Menu_Update
            sb.AppendLine("void Menu_Update(void) {");
            sb.AppendLine("    if (menu_state.mode == MENU_MODE_NONE) return;");
            sb.AppendLine("    if (!menu_state.needs_redraw) return;");
            sb.AppendLine();
            sb.AppendLine("    uint8_t parent      = menu_items[menu_state.current_item].parent;");
            sb.AppendLine("    const char* title   = (parent == 0) ? menu_items[0].name : menu_items[parent].name;");
            sb.AppendLine("    uint8_t first_child = menu_items[parent].first_child;");
            sb.AppendLine("    uint8_t last_child  = menu_items[parent].last_child;");
            sb.AppendLine("    uint8_t items_to_draw = MENU_DISPLAY_LINES;");
            sb.AppendLine("    bool full_redraw = (menu_state.prev_mode == MENU_MODE_NONE);");
            sb.AppendLine();
            sb.AppendLine("    bool title_changed = full_redraw ||");
            sb.AppendLine("                         (menu_state.prev_mode != menu_state.mode) ||");
            sb.AppendLine("                         (menu_state.prev_parent != parent);");
            sb.AppendLine();
            sb.AppendLine("    if (full_redraw) ST7735_FillScreen(MENU_BG_COLOR);");
            sb.AppendLine();
            sb.AppendLine("    if (title_changed) {");
            sb.AppendLine("        ST7735_FillRectangle(0, 0, ST7735_WIDTH, 14, MENU_BG_COLOR);");
            sb.AppendLine("        ST7735_WriteString(5, 2, title, Font_7x10, ST7735_YELLOW, MENU_BG_COLOR);");
            sb.AppendLine("        ST7735_FillRectangle(0, 14, ST7735_WIDTH, 1, MENU_TITLE_COLOR);");
            sb.AppendLine("        if (menu_state.prev_parent != parent) {");
            sb.AppendLine("            ST7735_FillRectangle(0, 18, ST7735_WIDTH,");
            sb.AppendLine("                MENU_DISPLAY_LINES * MENU_LINE_HEIGHT, MENU_BG_COLOR);");
            sb.AppendLine("            for (int i = 0; i < MENU_DISPLAY_LINES; i++)");
            sb.AppendLine("                menu_state.prev_display_ids[i] = 0xFF;");
            sb.AppendLine("        }");
            sb.AppendLine("    }");
            sb.AppendLine();
            sb.AppendLine("    for (uint8_t i = 0; i < items_to_draw; i++) {");
            sb.AppendLine("        uint8_t item_index = menu_state.display_start + i;");
            sb.AppendLine("        if (item_index > last_child) {");
            sb.AppendLine("            if (full_redraw || menu_state.prev_display_ids[i] != 0xFF) {");
            sb.AppendLine("                ST7735_FillRectangle(0, 18 + i * MENU_LINE_HEIGHT,");
            sb.AppendLine("                    ST7735_WIDTH, MENU_LINE_HEIGHT, MENU_BG_COLOR);");
            sb.AppendLine("                menu_state.prev_display_ids[i] = 0xFF;");
            sb.AppendLine("            }");
            sb.AppendLine("            break;");
            sb.AppendLine("        }");
            sb.AppendLine("        bool selected = (item_index == menu_state.current_item);");
            sb.AppendLine("        bool need = full_redraw;");
            sb.AppendLine("        if (!need && menu_state.prev_display_ids[i] != item_index) need = true;");
            sb.AppendLine("        if (!need && menu_state.prev_selected_line != menu_state.selected_line)");
            sb.AppendLine("            if ((i == menu_state.selected_line) || (i == menu_state.prev_selected_line)) need = true;");
            sb.AppendLine("        if (!need && menu_state.value_changed && (i == menu_state.selected_line)) need = true;");
            sb.AppendLine("        if (!need && menu_state.prev_mode != menu_state.mode) need = true;");
            sb.AppendLine("        if (need) {");
            sb.AppendLine("            Menu_DrawItemLine(i, item_index, selected);");
            sb.AppendLine("            menu_state.prev_display_ids[i] = item_index;");
            sb.AppendLine("        }");
            sb.AppendLine("    }");
            sb.AppendLine();
            sb.AppendLine("    if (full_redraw || menu_state.prev_mode != menu_state.mode ||");
            sb.AppendLine("        menu_state.prev_mode == MENU_MODE_EDIT || menu_state.mode == MENU_MODE_EDIT) {");
            sb.AppendLine("        ST7735_FillRectangle(ST7735_WIDTH - 28, 2, 28, 12, MENU_BG_COLOR);");
            sb.AppendLine("        if (menu_state.mode == MENU_MODE_EDIT)");
            sb.AppendLine("            ST7735_WriteString(ST7735_WIDTH - 20, 2, \"ED\", Font_7x10, MENU_MODE_ED_COLOR, MENU_BG_COLOR);");
            sb.AppendLine("    }");
            sb.AppendLine();
            sb.AppendLine("    uint8_t total_items = last_child - menu_items[parent].first_child + 1;");
            sb.AppendLine("    if (total_items > MENU_DISPLAY_LINES)");
            sb.AppendLine("        Menu_DrawScrollbar(total_items);");
            sb.AppendLine("    else");
            sb.AppendLine("        ST7735_FillRectangle(ST7735_WIDTH - 3, 18, 3,");
            sb.AppendLine("            MENU_DISPLAY_LINES * MENU_LINE_HEIGHT, MENU_BG_COLOR);");
            sb.AppendLine();
            sb.AppendLine("    menu_state.prev_mode          = menu_state.mode;");
            sb.AppendLine("    menu_state.prev_selected_line = menu_state.selected_line;");
            sb.AppendLine("    menu_state.prev_parent        = parent;");
            sb.AppendLine("    menu_state.needs_redraw       = false;");
            sb.AppendLine("    menu_state.value_changed      = false;");
            sb.AppendLine("}");
            sb.AppendLine();

            // NavigateUp
            sb.AppendLine("bool Menu_NavigateUp(void) {");
            sb.AppendLine("    if (menu_state.mode == MENU_MODE_BROWSE) {");
            sb.AppendLine("        uint8_t parent      = menu_items[menu_state.current_item].parent;");
            sb.AppendLine("        uint8_t first_child = menu_items[parent].first_child;");
            sb.AppendLine("        if (menu_state.current_item > first_child) {");
            sb.AppendLine("            menu_state.current_item--;");
            sb.AppendLine("            if (menu_state.selected_line > 0) menu_state.selected_line--;");
            sb.AppendLine("            else if (menu_state.display_start > first_child) menu_state.display_start--;");
            sb.AppendLine("            menu_state.needs_redraw = true;");
            sb.AppendLine("            return true;");
            sb.AppendLine("        }");
            sb.AppendLine("        return false;");
            sb.AppendLine("    }");
            sb.AppendLine("    else if (menu_state.mode == MENU_MODE_EDIT) {");
            sb.AppendLine("        MenuItemDef* item = &menu_items[menu_state.current_item];");
            sb.AppendLine("        if (item->value < item->max_value) {");
            sb.AppendLine("            item->value += item->step;");
            sb.AppendLine("            if (item->value > item->max_value) item->value = item->max_value;");
            sb.AppendLine("            menu_state.needs_redraw  = true;");
            sb.AppendLine("            menu_state.value_changed = true;");
            sb.AppendLine("            return true;");
            sb.AppendLine("        }");
            sb.AppendLine("        return false;");
            sb.AppendLine("    }");
            sb.AppendLine("    return false;");
            sb.AppendLine("}");
            sb.AppendLine();

            // NavigateDown
            sb.AppendLine("bool Menu_NavigateDown(void) {");
            sb.AppendLine("    if (menu_state.mode == MENU_MODE_BROWSE) {uint8_t parent = menu_items[menu_state.current_item].parent; ");
            sb.AppendLine("        uint8_t last_child = menu_items[parent].last_child;");
            sb.AppendLine("        if (menu_state.current_item < last_child) {");
            sb.AppendLine("            menu_state.current_item++;");
            sb.AppendLine("            if (menu_state.selected_line < MENU_DISPLAY_LINES - 1) menu_state.selected_line++;");
            sb.AppendLine("            else if (menu_state.display_start < last_child - (MENU_DISPLAY_LINES - 1)) menu_state.display_start++;");
            sb.AppendLine("            menu_state.needs_redraw = true;");
            sb.AppendLine("            return true;");
            sb.AppendLine("        }");
            sb.AppendLine("        return false;");
            sb.AppendLine("    }");
            sb.AppendLine("    else if (menu_state.mode == MENU_MODE_EDIT) {");
            sb.AppendLine("        MenuItemDef* item = &menu_items[menu_state.current_item];");
            sb.AppendLine("        if (item->value > item->min_value) {");
            sb.AppendLine("            if (item->value >= item->step) item->value -= item->step;");
            sb.AppendLine("            else item->value = item->min_value;");
            sb.AppendLine("            menu_state.needs_redraw  = true;");
            sb.AppendLine("            menu_state.value_changed = true;");
            sb.AppendLine("            return true;");
            sb.AppendLine("        }");
            sb.AppendLine("        return false;");
            sb.AppendLine("    }");
            sb.AppendLine("    return false;");
            sb.AppendLine("}");
            sb.AppendLine();

            // NavigateLeft
            sb.AppendLine("bool Menu_NavigateLeft(void) {");
            sb.AppendLine("    if (menu_state.mode == MENU_MODE_EDIT) {");
            sb.AppendLine("        menu_state.mode          = MENU_MODE_BROWSE;");
            sb.AppendLine("        menu_state.needs_redraw  = true;");
            sb.AppendLine("        menu_state.value_changed = false;");
            sb.AppendLine("        menu_state.prev_mode     = MENU_MODE_NONE;");
            sb.AppendLine("        for (int i = 0; i < MENU_DISPLAY_LINES; i++)");
            sb.AppendLine("            menu_state.prev_display_ids[i] = 0xFF;");
            sb.AppendLine("        if (save_callback) save_callback();");
            sb.AppendLine("        return true;");
            sb.AppendLine("    }");
            sb.AppendLine("    else if (menu_state.mode == MENU_MODE_BROWSE) {");
            sb.AppendLine("        uint8_t parent = menu_items[menu_state.current_item].parent;");
            sb.AppendLine("        if (parent != menu_state.current_item && parent != 0) {");
            sb.AppendLine("            menu_state.current_item = parent;");
            sb.AppendLine("            Menu_UpdateDisplayRange();");
            sb.AppendLine("            menu_state.needs_redraw = true;");
            sb.AppendLine("            return true;");
            sb.AppendLine("        }");
            sb.AppendLine("        return false;");
            sb.AppendLine("    }");
            sb.AppendLine("    return false;");
            sb.AppendLine("}");
            sb.AppendLine();

            // NavigateRight
            sb.AppendLine("bool Menu_NavigateRight(void) {");
            sb.AppendLine("    if (menu_state.mode == MENU_MODE_BROWSE) {");
            sb.AppendLine("        MenuItemDef* item = &menu_items[menu_state.current_item];");
            sb.AppendLine("        if (Menu_HasChildren(menu_state.current_item)) {");
            sb.AppendLine("            menu_state.current_item  = item->first_child;");
            sb.AppendLine("            menu_state.display_start = item->first_child;");
            sb.AppendLine("            menu_state.selected_line = 0;");
            sb.AppendLine("            menu_state.needs_redraw  = true;");
            sb.AppendLine("            return true;");
            sb.AppendLine("        }");
            sb.AppendLine("        else if (item->type != MENU_TYPE_FOLDER &&");
            sb.AppendLine("                 item->type != MENU_TYPE_INFO   &&");
            sb.AppendLine("                 item->type != MENU_TYPE_ACTION) {");
            sb.AppendLine("            menu_state.mode         = MENU_MODE_EDIT;");
            sb.AppendLine("            menu_state.needs_redraw = true;");
            sb.AppendLine("            return true;");
            sb.AppendLine("        }");
            sb.AppendLine("        else if (item->type == MENU_TYPE_ACTION) {");

            // Генерация action-обработчиков
            for (int i = 0; i < flat.Count; i++)
            {
                if (flat[i].Type == MenuItemType.ACTION)
                {
                    if (i == flat.Count - 1 || flat[i + 1].Type != MenuItemType.ACTION)
                        sb.AppendLine($"            if (menu_state.current_item == {i}) Menu_ResetSettings();");
                    else
                        sb.AppendLine($"            if (menu_state.current_item == {i}) Menu_ResetSettings();");
                }
            }

            sb.AppendLine("            return true;");
            sb.AppendLine("        }");
            sb.AppendLine("        return false;");
            sb.AppendLine("    }");
            sb.AppendLine("    else if (menu_state.mode == MENU_MODE_EDIT) {");
            sb.AppendLine("        menu_state.mode         = MENU_MODE_BROWSE;");
            sb.AppendLine("        menu_state.needs_redraw = true;");
            sb.AppendLine("        if (menu_state.value_changed && save_callback) {");
            sb.AppendLine("            save_callback();");
            sb.AppendLine("            menu_state.value_changed = false;");
            sb.AppendLine("            MenuItemDef* item = &menu_items[menu_state.current_item];");
            sb.AppendLine("            if (item->type >= MENU_TYPE_YEAR &&");
            sb.AppendLine("                item->type <= MENU_TYPE_MINUTE && time_callback)");
            sb.AppendLine("                time_callback();");
            sb.AppendLine("        }");
            sb.AppendLine("        return true;");
            sb.AppendLine("    }");
            sb.AppendLine("    return false;");
            sb.AppendLine("}");
            sb.AppendLine();

            // Menu_DrawItemLine
            sb.AppendLine("static void Menu_DrawItemLine(uint8_t line, uint8_t item_id, bool selected) {");
            sb.AppendLine("    uint16_t y           = 18 + line * MENU_LINE_HEIGHT;");
            sb.AppendLine("    uint16_t bg_color    = selected ? MENU_SELECTED_BG_COLOR : MENU_BG_COLOR;");
            sb.AppendLine("    uint16_t text_color  = selected ? MENU_SELECTED_TEXT_COLOR : MENU_TEXT_COLOR;");
            sb.AppendLine("    uint16_t text_bg_color = selected ? MENU_SELECTED_ICON_COLOR : MENU_ICON_COLOR;");
            sb.AppendLine("    ST7735_FillRectangle(0, y, ST7735_WIDTH, MENU_LINE_HEIGHT, bg_color);");
            sb.AppendLine("    MenuItemDef* item = &menu_items[item_id];");
            sb.AppendLine("    const char* icon = \" \";");
            sb.AppendLine("    switch (item->type) {");
            sb.AppendLine("        case MENU_TYPE_FOLDER:  icon = Menu_HasChildren(item_id) ? \">\" : \" \"; break;");
            sb.AppendLine("        case MENU_TYPE_BOOLEAN: icon = item->value ? \"+\" : \"-\"; break;");
            sb.AppendLine("        case MENU_TYPE_ACTION:  icon = \"!\"; break;");
            sb.AppendLine("        default: icon = \" \"; break;");
            sb.AppendLine("    }");
            sb.AppendLine("    ST7735_WriteString(MENU_TEXT_X_OFFSET, y + MENU_TEXT_Y_OFFSET,");
            sb.AppendLine("        icon, Font_7x10, text_bg_color, bg_color);");
            sb.AppendLine("    ST7735_WriteString(MENU_TEXT_X_OFFSET + 10, y + MENU_TEXT_Y_OFFSET,");
            sb.AppendLine("        menu_items[item_id].name, Font_7x10, text_color, bg_color);");
            sb.AppendLine("    if (item->type != MENU_TYPE_FOLDER && item->type != MENU_TYPE_ACTION) {");
            sb.AppendLine("        char value_str[16];");
            sb.AppendLine("        Menu_FormatValue(item_id, value_str, sizeof(value_str));");
            sb.AppendLine("        uint16_t value_color = (selected && menu_state.mode == MENU_MODE_EDIT)");
            sb.AppendLine("                             ? MENU_EDIT_COLOR : MENU_VALUE_COLOR;");
            sb.AppendLine("        uint8_t text_width = strlen(value_str) * 7;");
            sb.AppendLine("        uint8_t value_x    = ST7735_WIDTH - text_width - 5;");
            sb.AppendLine("        ST7735_WriteString(value_x, y + MENU_TEXT_Y_OFFSET,");
            sb.AppendLine("            value_str, Font_7x10, value_color, bg_color);");
            sb.AppendLine("    }");
            sb.AppendLine("}");
            sb.AppendLine();

            // Menu_FormatValue
            sb.AppendLine("static void Menu_FormatValue(uint8_t item_id, char* buffer, size_t buffer_size) {");
            sb.AppendLine("    MenuItemDef* item = &menu_items[item_id];");
            sb.AppendLine("    switch (item->type) {");
            sb.AppendLine("        case MENU_TYPE_BOOLEAN:          snprintf(buffer, buffer_size, \"%s\", item->value ? \"On\" : \"Off\"); break;");
            sb.AppendLine("        case MENU_TYPE_TEMPERATURE:");
            sb.AppendLine("        case MENU_TYPE_TEMPERATURE_HIGH: snprintf(buffer, buffer_size, \"%uC\", item->value); break;");
            sb.AppendLine("        case MENU_TYPE_PERCENTAGE:       snprintf(buffer, buffer_size, \"%u%%\", item->value); break;");
            sb.AppendLine("        case MENU_TYPE_YEAR:             snprintf(buffer, buffer_size, \"%u\", item->value); break;");
            sb.AppendLine("        case MENU_TYPE_MONTH:");
            sb.AppendLine("        case MENU_TYPE_DAY:              snprintf(buffer, buffer_size, \"%02u\", item->value); break;");
            sb.AppendLine("        case MENU_TYPE_HOUR:             snprintf(buffer, buffer_size, \"%02u:--\", item->value); break;");
            sb.AppendLine("        case MENU_TYPE_MINUTE:           snprintf(buffer, buffer_size, \"--%02u\", item->value); break;");
            sb.AppendLine("        case MENU_TYPE_INFO:             snprintf(buffer, buffer_size, \"v1.0\"); break;");
            sb.AppendLine("        default:                         snprintf(buffer, buffer_size, \"%u\", item->value); break;");
            sb.AppendLine("    }");
            sb.AppendLine("}");
            sb.AppendLine();

            // Menu_DrawScrollbar
            sb.AppendLine("void Menu_DrawScrollbar(uint8_t total_items) {");
            sb.AppendLine("    uint8_t scrollbar_x      = ST7735_WIDTH - 3;");
            sb.AppendLine("    uint8_t scrollbar_y      = 18;");
            sb.AppendLine("    uint8_t scrollbar_height = MENU_DISPLAY_LINES * MENU_LINE_HEIGHT;");
            sb.AppendLine("    ST7735_FillRectangle(scrollbar_x, scrollbar_y, 3, scrollbar_height, MENU_SCROLLBAR_BG_COLOR);");
            sb.AppendLine("    uint8_t thumb_height = (scrollbar_height * MENU_DISPLAY_LINES) / total_items;");
            sb.AppendLine("    if (thumb_height < 4) thumb_height = 4;");
            sb.AppendLine("    uint8_t parent      = menu_items[menu_state.current_item].parent;");
            sb.AppendLine("    uint8_t first_child = menu_items[parent].first_child;");
            sb.AppendLine("    uint8_t scroll_pos  = menu_state.display_start - first_child;");
            sb.AppendLine("    uint8_t thumb_y     = scrollbar_y + (scroll_pos * (scrollbar_height - thumb_height))");
            sb.AppendLine("                        / (total_items - MENU_DISPLAY_LINES);");
            sb.AppendLine("    ST7735_FillRectangle(scrollbar_x, thumb_y, 3, thumb_height, MENU_SCROLLBAR_COLOR);");
            sb.AppendLine("}");
            sb.AppendLine();

            // Menu_HasChildren
            sb.AppendLine("static bool Menu_HasChildren(uint8_t item_id) {");
            sb.AppendLine("    return menu_items[item_id].first_child != 0 &&");
            sb.AppendLine("           menu_items[item_id].last_child  != 0 &&");
            sb.AppendLine("           menu_items[item_id].first_child <= menu_items[item_id].last_child;");
            sb.AppendLine("}");
            sb.AppendLine();

            // Menu_UpdateDisplayRange
            sb.AppendLine("static void Menu_UpdateDisplayRange(void) {");
            sb.AppendLine("    uint8_t parent      = menu_items[menu_state.current_item].parent;");
            sb.AppendLine("    uint8_t first_child = menu_items[parent].first_child;");
            sb.AppendLine("    uint8_t last_child  = menu_items[parent].last_child;");
            sb.AppendLine("    if (menu_state.current_item < first_child || menu_state.current_item > last_child) {");
            sb.AppendLine("        menu_state.display_start = first_child;");
            sb.AppendLine("        menu_state.selected_line = 0;");
            sb.AppendLine("    } else {");
            sb.AppendLine("        menu_state.display_start = first_child;");
            sb.AppendLine("        menu_state.selected_line = menu_state.current_item - first_child;");
            sb.AppendLine("        if (menu_state.selected_line >= MENU_DISPLAY_LINES) {");
            sb.AppendLine("            menu_state.display_start = menu_state.current_item - MENU_DISPLAY_LINES + 1;");
            sb.AppendLine("            menu_state.selected_line = MENU_DISPLAY_LINES - 1;");
            sb.AppendLine("        }");
            sb.AppendLine("    }");
            sb.AppendLine("}");
            sb.AppendLine();

            // Menu_ResetSettings
            sb.AppendLine("void Menu_ResetSettings(void) {");
            sb.AppendLine("    for (uint8_t i = 0; i < MENU_MAX_ITEMS; i++) {");
            sb.AppendLine("        MenuItemDef* item = &menu_items[i];");
            sb.AppendLine("        switch (item->type) {");
            sb.AppendLine("            case MENU_TYPE_TEMPERATURE:      item->value = 20;   break;");
            sb.AppendLine("            case MENU_TYPE_TEMPERATURE_HIGH: item->value = 80;   break;");
            sb.AppendLine("            case MENU_TYPE_BOOLEAN:          item->value = 0;    break;");
            sb.AppendLine("            case MENU_TYPE_YEAR:             item->value = 2024; break;");
            sb.AppendLine("            case MENU_TYPE_MONTH:            item->value = 1;    break;");
            sb.AppendLine("            case MENU_TYPE_DAY:              item->value = 1;    break;");
            sb.AppendLine("            case MENU_TYPE_HOUR:");
            sb.AppendLine("            case MENU_TYPE_MINUTE:           item->value = 0;    break;");
            sb.AppendLine("            default: break;");
            sb.AppendLine("        }");
            sb.AppendLine("    }");
            sb.AppendLine("    Sound_PlayEffect(SOUND_MENU_RESET);");
            sb.AppendLine("    menu_state.needs_redraw = true;");
            sb.AppendLine("    if (save_callback) save_callback();");
            sb.AppendLine("}");
            sb.AppendLine();

            // Menu_ResetWiFi
            sb.AppendLine("void Menu_ResetWiFi(void) {");
            sb.AppendLine("    Sound_PlayEffect(SOUND_MENU_ACTION);");
            sb.AppendLine("}");
            sb.AppendLine();

            // Callbacks
            sb.AppendLine("void Menu_SetSaveCallback(MenuSaveCallback callback) {");
            sb.AppendLine("    save_callback = callback;");
            sb.AppendLine("}");
            sb.AppendLine();
            sb.AppendLine("void Menu_SetTimeCallback(MenuTimeCallback callback) {");
            sb.AppendLine("    time_callback = callback;");
            sb.AppendLine("}");
            sb.AppendLine();

            // Get/Set
            sb.AppendLine("uint16_t Menu_GetValue(uint8_t item_id) {");
            sb.AppendLine("    if (item_id >= MENU_MAX_ITEMS) return 0;");
            sb.AppendLine("    return menu_items[item_id].value;");
            sb.AppendLine("}");
            sb.AppendLine();
            sb.AppendLine("void Menu_SetValue(uint8_t item_id, uint16_t value) {");
            sb.AppendLine("    if (item_id >= MENU_MAX_ITEMS) return;");
            sb.AppendLine("    MenuItemDef* item = &menu_items[item_id];");
            sb.AppendLine("    if (value >= item->min_value && value <= item->max_value) {");
            sb.AppendLine("        item->value = value;");
            sb.AppendLine("        menu_state.needs_redraw = true;");
            sb.AppendLine("    }");
            sb.AppendLine("}");
            sb.AppendLine();

            // IsVisible / GetMode
            sb.AppendLine("bool Menu_IsVisible(void) {");
            sb.AppendLine("    return menu_state.mode != MENU_MODE_NONE;");
            sb.AppendLine("}");
            sb.AppendLine();
            sb.AppendLine("MenuMode Menu_GetMode(void) {");
            sb.AppendLine("    return menu_state.mode;");
            sb.AppendLine("}");

            return sb.ToString();
        }
    }
}
