#include "RoomCardWidgetBase.hpp"
#include "../Fonts.hpp"
#include "../WidgetManager.hpp"
#include "esp_log.h"
#include <cstring>
#include <cstdio>
#include <cmath>

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

RoomCardWidgetBase::RoomCardWidgetBase(const WidgetConfig& config)
    : Widget(config)
{
    roomName_[0] = '\0';
    tempFormat_[0] = '\0';
    for (size_t i = 0; i < MAX_SUBBUTTONS; ++i) {
        subButtonStates_[i] = false;
    }
}

RoomCardWidgetBase::~RoomCardWidgetBase() {
    // Sub-buttons are on screen parent, not on obj_, so delete them explicitly
    for (size_t i = 0; i < MAX_SUBBUTTONS; ++i) {
        if (subButtonObjs_[i] && lv_obj_is_valid(subButtonObjs_[i])) {
            lv_obj_delete(subButtonObjs_[i]);
            subButtonObjs_[i] = nullptr;
        }
    }
}

void RoomCardWidgetBase::clearLvglObject() {
    for (size_t i = 0; i < MAX_SUBBUTTONS; ++i) {
        subButtonObjs_[i] = nullptr;
        subButtonIcons_[i] = nullptr;
    }
    roomLabel_ = nullptr;
    tempLabel_ = nullptr;
    obj_ = nullptr;
}

int RoomCardWidgetBase::encodeUtf8(uint32_t codepoint, char* buf) {
    if (codepoint < 0x80) {
        buf[0] = static_cast<char>(codepoint);
        buf[1] = '\0';
        return 1;
    } else if (codepoint < 0x800) {
        buf[0] = static_cast<char>(0xC0 | (codepoint >> 6));
        buf[1] = static_cast<char>(0x80 | (codepoint & 0x3F));
        buf[2] = '\0';
        return 2;
    } else if (codepoint < 0x10000) {
        buf[0] = static_cast<char>(0xE0 | (codepoint >> 12));
        buf[1] = static_cast<char>(0x80 | ((codepoint >> 6) & 0x3F));
        buf[2] = static_cast<char>(0x80 | (codepoint & 0x3F));
        buf[3] = '\0';
        return 3;
    } else if (codepoint < 0x110000) {
        buf[0] = static_cast<char>(0xF0 | (codepoint >> 18));
        buf[1] = static_cast<char>(0x80 | ((codepoint >> 12) & 0x3F));
        buf[2] = static_cast<char>(0x80 | ((codepoint >> 6) & 0x3F));
        buf[3] = static_cast<char>(0x80 | (codepoint & 0x3F));
        buf[4] = '\0';
        return 4;
    }
    buf[0] = '\0';
    return 0;
}

void RoomCardWidgetBase::parseTextBase() {
    roomName_[0] = '\0';
    tempFormat_[0] = '\0';

    const char* text = config_.text;
    if (text && text[0] != '\0') {
        const char* newline = strchr(text, '\n');
        if (newline) {
            size_t nameLen = static_cast<size_t>(newline - text);
            if (nameLen >= MAX_TEXT_LEN) nameLen = MAX_TEXT_LEN - 1;
            memcpy(roomName_, text, nameLen);
            roomName_[nameLen] = '\0';

            strncpy(tempFormat_, newline + 1, MAX_TEXT_LEN - 1);
            tempFormat_[MAX_TEXT_LEN - 1] = '\0';
        } else {
            strncpy(roomName_, text, MAX_TEXT_LEN - 1);
            roomName_[MAX_TEXT_LEN - 1] = '\0';
        }
    }
}

void RoomCardWidgetBase::createSubButtonsCommon() {
    int16_t subBtnSize = config_.subButtonSize > 0 ? config_.subButtonSize : 40;

    for (uint8_t i = 0; i < config_.subButtonCount && i < MAX_SUBBUTTONS; ++i) {
        const SubButtonConfig& cfg = config_.subButtons[i];
        if (!cfg.enabled) continue;

        // Create sub-button on screen parent (not on widget container) to avoid clipping
        lv_obj_t* btn = lv_obj_create(screenParent_);
        lv_obj_remove_style_all(btn);
        lv_obj_set_size(btn, subBtnSize, subBtnSize);
        lv_obj_clear_flag(btn, LV_OBJ_FLAG_SCROLLABLE);
        lv_obj_add_flag(btn, LV_OBJ_FLAG_CLICKABLE);

        // Circular shape
        lv_obj_set_style_radius(btn, LV_RADIUS_CIRCLE, 0);
        lv_obj_set_style_bg_opa(btn, config_.subButtonOpacity, 0);

        // Position using layout-specific calculation
        int16_t relX, relY;
        calculateSubButtonPosition(i, cfg, relX, relY);
        int16_t absX = config_.x + relX;
        int16_t absY = config_.y + relY;
        lv_obj_set_pos(btn, absX, absY);

        // Create icon (use iconCodepointOff initially, will be updated based on state)
        uint32_t initialIcon = cfg.iconCodepointOff;
        if (initialIcon > 0 && Fonts::hasIconFont()) {
            lv_obj_t* icon = lv_label_create(btn);
            lv_obj_clear_flag(icon, LV_OBJ_FLAG_CLICKABLE);
            char iconText[5];
            encodeUtf8(initialIcon, iconText);
            lv_label_set_text(icon, iconText);
            lv_obj_center(icon);
            subButtonIcons_[i] = icon;
        }

        // Store index in user_data for click handler
        lv_obj_set_user_data(btn, reinterpret_cast<void*>(static_cast<uintptr_t>(i)));
        lv_obj_add_event_cb(btn, subButtonClickCallback, LV_EVENT_CLICKED, this);

        subButtonObjs_[i] = btn;
        subButtonStates_[i] = false;

        // Apply initial color (OFF state)
        updateSubButtonColor(i);
    }
}

void RoomCardWidgetBase::applySubButtonStyle() {
    uint8_t subBtnFontIdx = 1;  // Default small
    if (config_.subButtonSize > 55) {
        subBtnFontIdx = 3;
    } else if (config_.subButtonSize > 40) {
        subBtnFontIdx = 2;
    }
    const lv_font_t* subBtnIconFont = Fonts::iconFont(subBtnFontIdx);
    for (uint8_t i = 0; i < config_.subButtonCount && i < MAX_SUBBUTTONS; ++i) {
        if (subButtonIcons_[i] && subBtnIconFont) {
            lv_obj_set_style_text_font(subButtonIcons_[i], subBtnIconFont, 0);
            // Set initial icon color based on state (OFF by default)
            const Color& iconColor = subButtonStates_[i] ?
                config_.subButtons[i].iconColorOn : config_.subButtons[i].iconColorOff;
            lv_obj_set_style_text_color(subButtonIcons_[i], lv_color_hex(iconColor.toLvColor()), 0);
        }
    }
}

void RoomCardWidgetBase::updateSubButtonColor(uint8_t index) {
    if (index >= MAX_SUBBUTTONS || !subButtonObjs_[index]) return;

    const SubButtonConfig& cfg = config_.subButtons[index];
    bool isOn = subButtonStates_[index];

    // Update background color
    const Color& bgColor = isOn ? cfg.bgColorOn : cfg.bgColorOff;
    lv_obj_set_style_bg_color(subButtonObjs_[index], lv_color_hex(bgColor.toLvColor()), 0);

    // Update icon and icon color based on state
    if (subButtonIcons_[index]) {
        uint32_t iconCodepoint = isOn && cfg.iconCodepointOn > 0 ? cfg.iconCodepointOn : cfg.iconCodepointOff;
        if (iconCodepoint > 0) {
            char iconText[5];
            encodeUtf8(iconCodepoint, iconText);
            lv_label_set_text(subButtonIcons_[index], iconText);
        }

        // Set icon color
        const Color& iconColor = isOn ? cfg.iconColorOn : cfg.iconColorOff;
        lv_obj_set_style_text_color(subButtonIcons_[index], lv_color_hex(iconColor.toLvColor()), 0);
    }
}

void RoomCardWidgetBase::updateTemperature(float value) {
    if (!tempLabel_ || tempFormat_[0] == '\0') return;

    char buf[32];
    snprintf(buf, sizeof(buf), tempFormat_, value);
    lv_label_set_text(tempLabel_, buf);
}

void RoomCardWidgetBase::onKnxValue(float value) {
    cachedPrimaryValue_ = value;
    hasCachedPrimary_ = true;
    updateTemperature(value);
}

void RoomCardWidgetBase::onKnxSwitch(bool value) {
    // Not used directly - sub-button status is handled via onSubButtonStatus
    (void)value;
}

void RoomCardWidgetBase::onSubButtonStatus(uint8_t index, bool value) {
    if (index >= MAX_SUBBUTTONS) return;

    subButtonStates_[index] = value;
    updateSubButtonColor(index);
}

void RoomCardWidgetBase::sendSubButtonToggle(uint8_t index) {
    if (index >= config_.subButtonCount || index >= MAX_SUBBUTTONS) return;

    const SubButtonConfig& cfg = config_.subButtons[index];
    if (cfg.action == SubButtonAction::TOGGLE_KNX && cfg.knxAddrWrite > 0) {
        bool newState = !subButtonStates_[index];
        WidgetManager::instance().sendKnxSwitch(cfg.knxAddrWrite, newState);
        subButtonStates_[index] = newState;
        updateSubButtonColor(index);
    }
}

void RoomCardWidgetBase::cardClickCallback(lv_event_t* e) {
    RoomCardWidgetBase* widget = static_cast<RoomCardWidgetBase*>(lv_event_get_user_data(e));
    if (!widget) return;

    if (widget->config_.action == ButtonAction::JUMP) {
        WidgetManager::instance().navigateToScreen(widget->config_.targetScreen);
    } else if (widget->config_.action == ButtonAction::BACK) {
        WidgetManager::instance().navigateBack();
    }
}

void RoomCardWidgetBase::subButtonClickCallback(lv_event_t* e) {
    RoomCardWidgetBase* widget = static_cast<RoomCardWidgetBase*>(lv_event_get_user_data(e));
    lv_obj_t* target = static_cast<lv_obj_t*>(lv_event_get_target(e));
    if (!widget || !target) return;

    uint8_t index = static_cast<uint8_t>(reinterpret_cast<uintptr_t>(lv_obj_get_user_data(target)));

    if (index < widget->config_.subButtonCount && index < MAX_SUBBUTTONS) {
        const SubButtonConfig& cfg = widget->config_.subButtons[index];

        if (cfg.action == SubButtonAction::TOGGLE_KNX) {
            widget->sendSubButtonToggle(index);
        } else if (cfg.action == SubButtonAction::NAVIGATE) {
            WidgetManager::instance().navigateToScreen(cfg.targetScreen);
        }
    }
}
