#include "WifiSetting.hpp"
#include "../Wifi.hpp"
#include "../Fonts.hpp"
#include "esp_lv_adapter.h"
#include "esp_log.h"
#include <cstring>

static const char* TAG = "WifiSetting";

WifiSetting& WifiSetting::instance() {
    static WifiSetting instance;
    return instance;
}

void WifiSetting::show() {
    if (visible_) {
        return;
    }

    ESP_LOGI(TAG, "Showing WiFi settings");

    if (esp_lv_adapter_lock(-1) == ESP_OK) {
        createUI();
        visible_ = true;

        Wifi::instance().setStatusCallback([](bool connected) {
            if (esp_lv_adapter_lock(100) == ESP_OK) {
                WifiSetting::instance().updateStatusDisplay();
                esp_lv_adapter_unlock();
            }
        });

        refreshNetworkList();
        refreshSavedNetworks();
        updateStatusDisplay();

        esp_lv_adapter_unlock();
    }
}

void WifiSetting::hide() {
    if (!visible_) {
        return;
    }

    ESP_LOGI(TAG, "Hiding WiFi settings");

    if (esp_lv_adapter_lock(-1) == ESP_OK) {
        Wifi::instance().setStatusCallback(nullptr);

        if (overlay_) {
            lv_obj_del(overlay_);
            overlay_ = nullptr;
            statusLabel_ = nullptr;
            disconnectBtn_ = nullptr;
            networkList_ = nullptr;
            savedList_ = nullptr;
            passwordDialog_ = nullptr;
            passwordInput_ = nullptr;
            keyboard_ = nullptr;
        }
        visible_ = false;
        esp_lv_adapter_unlock();
    }
}

bool WifiSetting::isVisible() {
    return visible_;
}

void WifiSetting::createUI() {
    overlay_ = lv_obj_create(lv_scr_act());
    lv_obj_set_size(overlay_, LV_PCT(100), LV_PCT(100));
    lv_obj_set_style_bg_color(overlay_, lv_color_hex(0x202020), 0);
    lv_obj_set_style_bg_opa(overlay_, LV_OPA_COVER, 0);
    lv_obj_set_style_text_font(overlay_, Fonts::bySizeIndex(0), 0);
    lv_obj_set_style_pad_all(overlay_, 10, 0);
    lv_obj_clear_flag(overlay_, LV_OBJ_FLAG_SCROLLABLE);

    lv_obj_t* header = lv_obj_create(overlay_);
    lv_obj_set_size(header, LV_PCT(100), 50);
    lv_obj_align(header, LV_ALIGN_TOP_MID, 0, 0);
    lv_obj_set_style_bg_color(header, lv_color_hex(0x303030), 0);
    lv_obj_set_style_pad_all(header, 5, 0);
    lv_obj_clear_flag(header, LV_OBJ_FLAG_SCROLLABLE);

    lv_obj_t* closeBtn = lv_btn_create(header);
    lv_obj_set_size(closeBtn, 40, 40);
    lv_obj_align(closeBtn, LV_ALIGN_LEFT_MID, 0, 0);
    lv_obj_set_style_bg_color(closeBtn, lv_color_hex(0x804040), 0);
    //lv_obj_add_event_cb(closeBtn, onCloseClick, LV_EVENT_CLICKED, nullptr);

    lv_obj_t* closeLbl = lv_label_create(closeBtn);
    lv_label_set_text(closeLbl, "X");
    lv_obj_center(closeLbl);

    lv_obj_t* titleLbl = lv_label_create(header);
    lv_label_set_text(titleLbl, "WiFi Settings");
    lv_obj_set_style_text_font(titleLbl, Fonts::bySizeIndex(0), 0);
    lv_obj_align(titleLbl, LV_ALIGN_CENTER, 0, 0);

    lv_obj_t* statusSection = lv_obj_create(overlay_);
    lv_obj_set_size(statusSection, LV_PCT(100), 80);
    lv_obj_align_to(statusSection, header, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
    lv_obj_set_style_bg_color(statusSection, lv_color_hex(0x303030), 0);
    lv_obj_set_style_pad_all(statusSection, 10, 0);
    lv_obj_clear_flag(statusSection, LV_OBJ_FLAG_SCROLLABLE);

    statusLabel_ = lv_label_create(statusSection);
    lv_label_set_text(statusLabel_, "Status: Nicht verbunden");
    lv_obj_align(statusLabel_, LV_ALIGN_LEFT_MID, 0, 0);

    disconnectBtn_ = lv_btn_create(statusSection);
    lv_obj_set_size(disconnectBtn_, 100, 40);
    lv_obj_align(disconnectBtn_, LV_ALIGN_RIGHT_MID, 0, 0);
    //lv_obj_add_event_cb(disconnectBtn_, onDisconnectClick, LV_EVENT_CLICKED, nullptr);
    lv_obj_add_flag(disconnectBtn_, LV_OBJ_FLAG_HIDDEN);

    lv_obj_t* disconnectLbl = lv_label_create(disconnectBtn_);
    lv_label_set_text(disconnectLbl, "Trennen");
    lv_obj_center(disconnectLbl);

    lv_obj_t* availableSection = lv_obj_create(overlay_);
    lv_obj_set_size(availableSection, LV_PCT(100), 280);
    lv_obj_align_to(availableSection, statusSection, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
    lv_obj_set_style_bg_color(availableSection, lv_color_hex(0x303030), 0);
    lv_obj_set_style_pad_all(availableSection, 10, 0);
    lv_obj_clear_flag(availableSection, LV_OBJ_FLAG_SCROLLABLE);

    lv_obj_t* availableHeader = lv_obj_create(availableSection);
    lv_obj_set_size(availableHeader, LV_PCT(100), 40);
    lv_obj_align(availableHeader, LV_ALIGN_TOP_MID, 0, 0);
    lv_obj_set_style_bg_opa(availableHeader, LV_OPA_TRANSP, 0);
    lv_obj_set_style_border_width(availableHeader, 0, 0);
    lv_obj_set_style_pad_all(availableHeader, 0, 0);
    lv_obj_clear_flag(availableHeader, LV_OBJ_FLAG_SCROLLABLE);

    lv_obj_t* availableLbl = lv_label_create(availableHeader);
    lv_label_set_text(availableLbl, "Verfuegbare Netzwerke:");
    lv_obj_align(availableLbl, LV_ALIGN_LEFT_MID, 0, 0);

    lv_obj_t* scanBtn = lv_btn_create(availableHeader);
    lv_obj_set_size(scanBtn, 100, 35);
    lv_obj_align(scanBtn, LV_ALIGN_RIGHT_MID, 0, 0);
    //lv_obj_add_event_cb(scanBtn, onScanClick, LV_EVENT_CLICKED, nullptr);

    lv_obj_t* scanLbl = lv_label_create(scanBtn);
    lv_label_set_text(scanLbl, "Scannen");
    lv_obj_center(scanLbl);

    networkList_ = lv_list_create(availableSection);
    lv_obj_set_size(networkList_, LV_PCT(100), 220);
    lv_obj_align_to(networkList_, availableHeader, LV_ALIGN_OUT_BOTTOM_MID, 0, 5);
    lv_obj_set_style_bg_color(networkList_, lv_color_hex(0x252525), 0);

    lv_obj_t* savedSection = lv_obj_create(overlay_);
    lv_obj_set_size(savedSection, LV_PCT(100), 200);
    lv_obj_align_to(savedSection, availableSection, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
    lv_obj_set_style_bg_color(savedSection, lv_color_hex(0x303030), 0);
    lv_obj_set_style_pad_all(savedSection, 10, 0);
    lv_obj_clear_flag(savedSection, LV_OBJ_FLAG_SCROLLABLE);

    lv_obj_t* savedLbl = lv_label_create(savedSection);
    lv_label_set_text(savedLbl, "Gespeicherte Netzwerke:");
    lv_obj_align(savedLbl, LV_ALIGN_TOP_LEFT, 0, 0);

    savedList_ = lv_list_create(savedSection);
    lv_obj_set_size(savedList_, LV_PCT(100), 150);
    lv_obj_align(savedList_, LV_ALIGN_BOTTOM_MID, 0, 0);
    lv_obj_set_style_bg_color(savedList_, lv_color_hex(0x252525), 0);
}

void WifiSetting::refreshNetworkList() {
    ESP_LOGI(TAG, "Starting network scan");

    if (networkList_) {
        lv_obj_clean(networkList_);
        lv_obj_t* scanningLbl = lv_list_add_text(networkList_, "Scanning...");
        (void)scanningLbl;
    }

    Wifi::instance().scan([](std::vector<wifi_ap_record_t>& networks) {
        WifiSetting& settings = WifiSetting::instance();
        settings.scannedNetworks_ = networks;

        if (esp_lv_adapter_lock(100) == ESP_OK) {
            if (settings.networkList_) {
                lv_obj_clean(settings.networkList_);

                for (const auto& ap : networks) {
                    char signalStr[64];
                    int bars = 0;
                    if (ap.rssi >= -50) bars = 4;
                    else if (ap.rssi >= -60) bars = 3;
                    else if (ap.rssi >= -70) bars = 2;
                    else bars = 1;

                    const char* barSymbols[] = {"[#   ]", "[##  ]", "[### ]", "[####]"};
                    snprintf(signalStr, sizeof(signalStr), "%s %s %ddBm",
                            (const char*)ap.ssid, barSymbols[bars - 1], ap.rssi);

                    lv_obj_t* btn = lv_list_add_btn(settings.networkList_, LV_SYMBOL_WIFI, signalStr);
                    //lv_obj_add_event_cb(btn, onNetworkSelect, LV_EVENT_CLICKED, nullptr);

                    size_t ssidLen = strlen((const char*)ap.ssid);
                    char* ssidCopy = (char*)lv_malloc(ssidLen + 1);
                    strcpy(ssidCopy, (const char*)ap.ssid);
                    lv_obj_set_user_data(btn, ssidCopy);
                }

                if (networks.empty()) {
                    lv_list_add_text(settings.networkList_, "Keine Netzwerke gefunden");
                }
            }
            esp_lv_adapter_unlock();
        }
    });
}

void WifiSetting::refreshSavedNetworks() {
    if (!savedList_) return;

    lv_obj_clean(savedList_);

    auto savedNetworks = Wifi::instance().getSavedNetworks();

    for (const auto& ssid : savedNetworks) {
        lv_obj_t* item = lv_obj_create(savedList_);
        lv_obj_set_size(item, LV_PCT(100), 40);
        lv_obj_set_style_bg_color(item, lv_color_hex(0x353535), 0);
        lv_obj_set_style_pad_all(item, 5, 0);
        lv_obj_clear_flag(item, LV_OBJ_FLAG_SCROLLABLE);

        lv_obj_t* nameLbl = lv_label_create(item);
        lv_label_set_text(nameLbl, ssid.c_str());
        lv_obj_align(nameLbl, LV_ALIGN_LEFT_MID, 0, 0);

        lv_obj_t* deleteBtn = lv_btn_create(item);
        lv_obj_set_size(deleteBtn, 80, 30);
        lv_obj_align(deleteBtn, LV_ALIGN_RIGHT_MID, 0, 0);
        lv_obj_set_style_bg_color(deleteBtn, lv_color_hex(0x804040), 0);
        //lv_obj_add_event_cb(deleteBtn, onDeleteSavedClick, LV_EVENT_CLICKED, nullptr);

        char* ssidCopy = (char*)lv_malloc(ssid.size() + 1);
        strcpy(ssidCopy, ssid.c_str());
        lv_obj_set_user_data(deleteBtn, ssidCopy);

        lv_obj_t* deleteLbl = lv_label_create(deleteBtn);
        lv_label_set_text(deleteLbl, "Loeschen");
        lv_obj_center(deleteLbl);
    }

    if (savedNetworks.empty()) {
        lv_list_add_text(savedList_, "Keine gespeicherten Netzwerke");
    }
}

void WifiSetting::updateStatusDisplay() {
    if (!statusLabel_ || !disconnectBtn_) return;

    Wifi& wifi = Wifi::instance();

    if (wifi.isConnected()) {
        char statusText[64];
        snprintf(statusText, sizeof(statusText), "Verbunden: %s", wifi.getCurrentSSID().c_str());
        lv_label_set_text(statusLabel_, statusText);
        lv_obj_clear_flag(disconnectBtn_, LV_OBJ_FLAG_HIDDEN);
    } else {
        lv_label_set_text(statusLabel_, "Status: Nicht verbunden");
        lv_obj_add_flag(disconnectBtn_, LV_OBJ_FLAG_HIDDEN);
    }
}

static void showPasswordDialogAsync(void* arg) {
    WifiSetting::instance().createPasswordDialogUI();
}

void WifiSetting::showPasswordDialog(const char* ssid) {
    selectedSSID_ = ssid;
    lv_async_call(showPasswordDialogAsync, nullptr);
}

void WifiSetting::createPasswordDialogUI() {
    if (passwordDialog_) return;

    ESP_LOGI(TAG, "Creating password dialog for: %s", selectedSSID_.c_str());

    passwordDialog_ = lv_obj_create(lv_scr_act());
    lv_obj_set_size(passwordDialog_, LV_PCT(100), LV_PCT(100));
    lv_obj_set_pos(passwordDialog_, 0, 0);
    lv_obj_set_style_bg_color(passwordDialog_, lv_color_hex(0x303030), 0);
    lv_obj_set_style_bg_opa(passwordDialog_, LV_OPA_COVER, 0);
    lv_obj_set_style_pad_all(passwordDialog_, 20, 0);
    lv_obj_clear_flag(passwordDialog_, LV_OBJ_FLAG_SCROLLABLE);

    char title[64];
    snprintf(title, sizeof(title), "Verbinden mit: %s", selectedSSID_.c_str());
    lv_obj_t* titleLbl = lv_label_create(passwordDialog_);
    lv_label_set_text(titleLbl, title);
    lv_obj_align(titleLbl, LV_ALIGN_TOP_MID, 0, 10);

    lv_obj_t* pwLabel = lv_label_create(passwordDialog_);
    lv_label_set_text(pwLabel, "Passwort:");
    lv_obj_align(pwLabel, LV_ALIGN_TOP_LEFT, 10, 50);

    passwordInput_ = lv_textarea_create(passwordDialog_);
    lv_obj_set_size(passwordInput_, LV_PCT(90), 50);
    lv_obj_align(passwordInput_, LV_ALIGN_TOP_MID, 0, 80);
    lv_textarea_set_password_mode(passwordInput_, true);
    lv_textarea_set_one_line(passwordInput_, true);
    lv_textarea_set_placeholder_text(passwordInput_, "Passwort eingeben...");

    lv_obj_t* cancelBtn = lv_btn_create(passwordDialog_);
    lv_obj_set_size(cancelBtn, 150, 50);
    lv_obj_align(cancelBtn, LV_ALIGN_TOP_LEFT, 20, 150);
    lv_obj_set_style_bg_color(cancelBtn, lv_color_hex(0x606060), 0);
    //lv_obj_add_event_cb(cancelBtn, onCancelClick, LV_EVENT_CLICKED, nullptr);

    lv_obj_t* cancelLbl = lv_label_create(cancelBtn);
    lv_label_set_text(cancelLbl, "Abbrechen");
    lv_obj_center(cancelLbl);

    lv_obj_t* connectBtn = lv_btn_create(passwordDialog_);
    lv_obj_set_size(connectBtn, 150, 50);
    lv_obj_align(connectBtn, LV_ALIGN_TOP_RIGHT, -20, 150);
    lv_obj_set_style_bg_color(connectBtn, lv_color_hex(0x408040), 0);
    //lv_obj_add_event_cb(connectBtn, onConnectClick, LV_EVENT_CLICKED, nullptr);

    lv_obj_t* connectLbl = lv_label_create(connectBtn);
    lv_label_set_text(connectLbl, "Verbinden");
    lv_obj_center(connectLbl);

    keyboard_ = lv_keyboard_create(passwordDialog_);
    lv_obj_set_size(keyboard_, LV_PCT(100), 300);
    lv_obj_align(keyboard_, LV_ALIGN_BOTTOM_MID, 0, 0);
    lv_keyboard_set_textarea(keyboard_, passwordInput_);
    //lv_obj_add_event_cb(keyboard_, onKeyboardReady, LV_EVENT_READY, nullptr);

    ESP_LOGI(TAG, "Password dialog created");
}

void WifiSetting::hidePasswordDialog() {
    if (passwordDialog_) {
        lv_obj_del(passwordDialog_);
        passwordDialog_ = nullptr;
        passwordInput_ = nullptr;
        keyboard_ = nullptr;
    }
    selectedSSID_.clear();
}

void WifiSetting::onCloseClick(lv_event_t* e) {
    (void)e;
    WifiSetting::instance().hide();
}

void WifiSetting::onNetworkSelect(lv_event_t* e) {
    lv_obj_t* btn = (lv_obj_t*)lv_event_get_target(e);
    char* ssid = (char*)lv_obj_get_user_data(btn);
    if (ssid) {
        ESP_LOGI(TAG, "Selected network: %s", ssid);
        WifiSetting::instance().showPasswordDialog(ssid);
    }
}

void WifiSetting::onScanClick(lv_event_t* e) {
    (void)e;
    WifiSetting::instance().refreshNetworkList();
}

void WifiSetting::onDisconnectClick(lv_event_t* e) {
    (void)e;
    Wifi::instance().disconnect();
    WifiSetting::instance().updateStatusDisplay();
}

void WifiSetting::onConnectClick(lv_event_t* e) {
    (void)e;
    WifiSetting& settings = WifiSetting::instance();

    if (settings.passwordInput_ && !settings.selectedSSID_.empty()) {
        const char* password = lv_textarea_get_text(settings.passwordInput_);

        ESP_LOGI(TAG, "Connecting to %s", settings.selectedSSID_.c_str());

        Wifi::instance().connect(settings.selectedSSID_.c_str(), password);
        Wifi::instance().saveNetwork(settings.selectedSSID_.c_str(), password);

        settings.hidePasswordDialog();
        settings.refreshSavedNetworks();
    }
}

void WifiSetting::onCancelClick(lv_event_t* e) {
    (void)e;
    WifiSetting::instance().hidePasswordDialog();
}

void WifiSetting::onDeleteSavedClick(lv_event_t* e) {
    lv_obj_t* btn = (lv_obj_t*)lv_event_get_target(e);
    char* ssid = (char*)lv_obj_get_user_data(btn);
    if (ssid) {
        ESP_LOGI(TAG, "Deleting saved network: %s", ssid);
        Wifi::instance().removeNetwork(ssid);
        lv_free(ssid);
        WifiSetting::instance().refreshSavedNetworks();
    }
}

void WifiSetting::onKeyboardReady(lv_event_t* e) {
    (void)e;
    onConnectClick(nullptr);
}
