#ifdef ESP_PLATFORM
#include <sdkconfig.h>
#endif

#if defined(CONFIG_SOC_WIFI_SUPPORTED) || defined(CONFIG_SLAVE_SOC_WIFI_SUPPORTED)

#include <Tactility/app/chat/ChatView.h>
#include <Tactility/app/chat/ChatAppPrivate.h>
#include <Tactility/app/chat/ChatProtocol.h>

#include <Tactility/lvgl/Toolbar.h>

#include <cstdio>
#include <cstring>

namespace tt::app::chat {

void ChatView::addMessageToList(lv_obj_t* list, const StoredMessage& msg) {
    auto* label = lv_label_create(list);
    lv_label_set_text(label, msg.displayText.c_str());
    lv_obj_set_width(label, lv_pct(100));
    lv_label_set_long_mode(label, LV_LABEL_LONG_WRAP);
    lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_LEFT, 0);
    lv_obj_set_style_pad_all(label, 2, 0);

    if (msg.isOwn) {
        if (lv_display_get_color_format(lv_obj_get_display(label)) != LV_COLOR_FORMAT_L8) {
            lv_obj_set_style_text_color(label, lv_color_hex(0x80C0FF), 0);
        }
    }
}

void ChatView::updateToolbarTitle() {
    if (!state || !toolbar) return;
    std::string channel = state->getCurrentChannel();
    std::string title = "Chat: " + channel;
    lvgl_toolbar_set_title(toolbar, title.c_str());
}

void ChatView::createInputBar(lv_obj_t* parent) {
    inputWrapper = lv_obj_create(parent);
    auto* wrapper = inputWrapper;
    lv_obj_set_flex_flow(wrapper, LV_FLEX_FLOW_ROW);
    lv_obj_set_size(wrapper, LV_PCT(100), LV_SIZE_CONTENT);
    lv_obj_set_style_pad_all(wrapper, 0, 0);
    lv_obj_set_style_pad_column(wrapper, 4, 0);
    lv_obj_set_style_border_opa(wrapper, 0, LV_STATE_DEFAULT);

    inputField = lv_textarea_create(wrapper);
    lv_obj_set_flex_grow(inputField, 1);
    lv_textarea_set_placeholder_text(inputField, "Type a message...");
    lv_textarea_set_one_line(inputField, true);
    lv_textarea_set_max_length(inputField, MAX_MESSAGE_LEN);

    auto* sendBtn = lv_button_create(wrapper);
    lv_obj_set_style_margin_all(sendBtn, 0, LV_STATE_DEFAULT);
    lv_obj_set_style_margin_top(sendBtn, 2, LV_STATE_DEFAULT);
    lv_obj_add_event_cb(sendBtn, onSendClicked, LV_EVENT_CLICKED, this);

    auto* btnLabel = lv_label_create(sendBtn);
    lv_label_set_text(btnLabel, "Send");
    lv_obj_center(btnLabel);
}

void ChatView::createSettingsPanel(lv_obj_t* parent) {
    settingsPanel = lv_obj_create(parent);
    lv_obj_set_width(settingsPanel, LV_PCT(100));
    lv_obj_set_flex_grow(settingsPanel, 1);
    lv_obj_set_flex_flow(settingsPanel, LV_FLEX_FLOW_COLUMN);
    lv_obj_set_style_pad_all(settingsPanel, 8, 0);
    lv_obj_set_style_pad_row(settingsPanel, 6, 0);
    lv_obj_add_flag(settingsPanel, LV_OBJ_FLAG_HIDDEN);

    // Nickname
    auto* nickLabel = lv_label_create(settingsPanel);
    lv_label_set_text(nickLabel, "Nickname (max 23):");

    nicknameInput = lv_textarea_create(settingsPanel);
    lv_obj_set_width(nicknameInput, LV_PCT(100));
    lv_textarea_set_one_line(nicknameInput, true);
    lv_textarea_set_max_length(nicknameInput, MAX_NICKNAME_LEN);

    // Encryption key
    auto* keyLabel = lv_label_create(settingsPanel);
    lv_label_set_text(keyLabel, "Key (32 hex chars):");

    keyInput = lv_textarea_create(settingsPanel);
    lv_obj_set_width(keyInput, LV_PCT(100));
    lv_textarea_set_one_line(keyInput, true);
    lv_textarea_set_max_length(keyInput, ESP_NOW_KEY_LEN * 2);
    lv_textarea_set_placeholder_text(keyInput, "empty = all zeros");

    // Buttons
    auto* btnRow = lv_obj_create(settingsPanel);
    lv_obj_set_flex_flow(btnRow, LV_FLEX_FLOW_ROW);
    lv_obj_set_size(btnRow, LV_PCT(100), LV_SIZE_CONTENT);
    lv_obj_set_style_pad_all(btnRow, 0, 0);
    lv_obj_set_style_pad_column(btnRow, 8, 0);
    lv_obj_set_style_border_opa(btnRow, 0, 0);

    auto* saveBtn = lv_button_create(btnRow);
    lv_obj_add_event_cb(saveBtn, onSettingsSave, LV_EVENT_CLICKED, this);
    auto* saveLbl = lv_label_create(saveBtn);
    lv_label_set_text(saveLbl, "Save");

    auto* cancelBtn = lv_button_create(btnRow);
    lv_obj_add_event_cb(cancelBtn, onSettingsCancel, LV_EVENT_CLICKED, this);
    auto* cancelLbl = lv_label_create(cancelBtn);
    lv_label_set_text(cancelLbl, "Cancel");
}

void ChatView::createChannelPanel(lv_obj_t* parent) {
    channelPanel = lv_obj_create(parent);
    lv_obj_set_width(channelPanel, LV_PCT(100));
    lv_obj_set_flex_grow(channelPanel, 1);
    lv_obj_set_flex_flow(channelPanel, LV_FLEX_FLOW_COLUMN);
    lv_obj_set_style_pad_all(channelPanel, 8, 0);
    lv_obj_set_style_pad_row(channelPanel, 6, 0);
    lv_obj_add_flag(channelPanel, LV_OBJ_FLAG_HIDDEN);

    auto* label = lv_label_create(channelPanel);
    lv_label_set_text(label, "Channel (e.g. #general):");

    channelInput = lv_textarea_create(channelPanel);
    lv_obj_set_width(channelInput, LV_PCT(100));
    lv_textarea_set_one_line(channelInput, true);
    lv_textarea_set_max_length(channelInput, MAX_TARGET_LEN);

    auto* btnRow = lv_obj_create(channelPanel);
    lv_obj_set_flex_flow(btnRow, LV_FLEX_FLOW_ROW);
    lv_obj_set_size(btnRow, LV_PCT(100), LV_SIZE_CONTENT);
    lv_obj_set_style_pad_all(btnRow, 0, 0);
    lv_obj_set_style_pad_column(btnRow, 8, 0);
    lv_obj_set_style_border_opa(btnRow, 0, 0);

    auto* okBtn = lv_button_create(btnRow);
    lv_obj_add_event_cb(okBtn, onChannelSave, LV_EVENT_CLICKED, this);
    auto* okLbl = lv_label_create(okBtn);
    lv_label_set_text(okLbl, "OK");

    auto* cancelBtn = lv_button_create(btnRow);
    lv_obj_add_event_cb(cancelBtn, onChannelCancel, LV_EVENT_CLICKED, this);
    auto* cancelLbl = lv_label_create(cancelBtn);
    lv_label_set_text(cancelLbl, "Cancel");
}

void ChatView::init(AppContext& appContext, lv_obj_t* parent) {
    lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
    lv_obj_set_style_pad_row(parent, 0, LV_STATE_DEFAULT);

    toolbar = lvgl::toolbar_create(parent, appContext);
    lvgl_toolbar_add_text_button_action(toolbar, LV_SYMBOL_LIST, onChannelClicked, this);
    lvgl_toolbar_add_text_button_action(toolbar, LV_SYMBOL_SETTINGS, onSettingsClicked, this);
    updateToolbarTitle();

    // Message list
    msgList = lv_list_create(parent);
    lv_obj_set_flex_grow(msgList, 1);
    lv_obj_set_width(msgList, LV_PCT(100));
    if (lv_display_get_color_format(lv_obj_get_display(parent)) != LV_COLOR_FORMAT_L8) {
        lv_obj_set_style_bg_color(msgList, lv_color_hex(0x262626), 0);
    }
    lv_obj_set_style_border_width(msgList, 0, 0);
    lv_obj_set_style_pad_ver(msgList, 2, 0);
    lv_obj_set_style_pad_hor(msgList, 4, 0);

    // Input bar
    createInputBar(parent);

    // Overlay panels (hidden by default)
    createSettingsPanel(parent);
    createChannelPanel(parent);
}

void ChatView::displayMessage(const StoredMessage& msg) {
    if (!msgList || !state) return;

    // Only show if matches current channel or broadcast
    std::string channel = state->getCurrentChannel();
    if (!msg.target.empty() && msg.target != channel) {
        return;
    }
    addMessageToList(msgList, msg);
    lv_obj_scroll_to_y(msgList, LV_COORD_MAX, LV_ANIM_ON);
}

void ChatView::refreshMessageList() {
    if (!msgList || !state) return;

    lv_obj_clean(msgList);
    auto filtered = state->getFilteredMessages();
    for (const auto& msg : filtered) {
        addMessageToList(msgList, msg);
    }
    lv_obj_scroll_to_y(msgList, LV_COORD_MAX, LV_ANIM_OFF);
    updateToolbarTitle();
}

void ChatView::showSettings(const ChatSettingsData& current) {
    if (!settingsPanel) return;

    lv_textarea_set_text(nicknameInput, current.nickname.c_str());

    if (current.hasEncryptionKey) {
        char hexStr[ESP_NOW_KEY_LEN * 2 + 1] = {};
        for (size_t i = 0; i < ESP_NOW_KEY_LEN; i++) {
            snprintf(hexStr + i * 2, 3, "%02x", current.encryptionKey[i]);
        }
        lv_textarea_set_text(keyInput, hexStr);
    } else {
        lv_textarea_set_text(keyInput, "");
    }

    lv_obj_add_flag(msgList, LV_OBJ_FLAG_HIDDEN);
    lv_obj_add_flag(inputWrapper, LV_OBJ_FLAG_HIDDEN);
    lv_obj_remove_flag(settingsPanel, LV_OBJ_FLAG_HIDDEN);
}

void ChatView::hideSettings() {
    if (!settingsPanel || !msgList || !inputWrapper) return;
    lv_obj_add_flag(settingsPanel, LV_OBJ_FLAG_HIDDEN);
    lv_obj_remove_flag(msgList, LV_OBJ_FLAG_HIDDEN);
    lv_obj_remove_flag(inputWrapper, LV_OBJ_FLAG_HIDDEN);
}

void ChatView::showChannelSelector() {
    if (!channelPanel || !state) return;

    std::string current = state->getCurrentChannel();
    lv_textarea_set_text(channelInput, current.c_str());

    lv_obj_add_flag(msgList, LV_OBJ_FLAG_HIDDEN);
    lv_obj_add_flag(inputWrapper, LV_OBJ_FLAG_HIDDEN);
    lv_obj_remove_flag(channelPanel, LV_OBJ_FLAG_HIDDEN);
}

void ChatView::hideChannelSelector() {
    if (!channelPanel || !msgList || !inputWrapper) return;
    lv_obj_add_flag(channelPanel, LV_OBJ_FLAG_HIDDEN);
    lv_obj_remove_flag(msgList, LV_OBJ_FLAG_HIDDEN);
    lv_obj_remove_flag(inputWrapper, LV_OBJ_FLAG_HIDDEN);
}

void ChatView::onSendClicked(lv_event_t* e) {
    auto* self = static_cast<ChatView*>(lv_event_get_user_data(e));
    auto* text = lv_textarea_get_text(self->inputField);
    if (text && strlen(text) > 0) {
        self->app->sendMessage(std::string(text));
        lv_textarea_set_text(self->inputField, "");
    }
}

void ChatView::onSettingsClicked(lv_event_t* e) {
    auto* self = static_cast<ChatView*>(lv_event_get_user_data(e));
    self->showSettings(self->app->getSettings());
}

void ChatView::onSettingsSave(lv_event_t* e) {
    auto* self = static_cast<ChatView*>(lv_event_get_user_data(e));

    auto* nickname = lv_textarea_get_text(self->nicknameInput);
    auto* keyHex = lv_textarea_get_text(self->keyInput);

    if (nickname && strlen(nickname) > 0) {
        self->app->applySettings(
            std::string(nickname),
            keyHex ? std::string(keyHex) : std::string()
        );
    }
    self->hideSettings();
}

void ChatView::onSettingsCancel(lv_event_t* e) {
    auto* self = static_cast<ChatView*>(lv_event_get_user_data(e));
    self->hideSettings();
}

void ChatView::onChannelClicked(lv_event_t* e) {
    auto* self = static_cast<ChatView*>(lv_event_get_user_data(e));
    self->showChannelSelector();
}

void ChatView::onChannelSave(lv_event_t* e) {
    auto* self = static_cast<ChatView*>(lv_event_get_user_data(e));
    auto* text = lv_textarea_get_text(self->channelInput);
    if (text && strlen(text) > 0) {
        self->app->switchChannel(std::string(text));
    }
    self->hideChannelSelector();
}

void ChatView::onChannelCancel(lv_event_t* e) {
    auto* self = static_cast<ChatView*>(lv_event_get_user_data(e));
    self->hideChannelSelector();
}

} // namespace tt::app::chat

#endif // CONFIG_SOC_WIFI_SUPPORTED || CONFIG_SLAVE_SOC_WIFI_SUPPORTED
