#include "Dashboard.hpp"
#include <WiFi.h>
#include <math.h>

namespace cyd {

Dashboard::Dashboard(CYD_Display& display, SettingsManager& settings, ThermoproBLE& bleClient)
    : display_(display), settings_(settings), bleClient_(bleClient) {
}

void Dashboard::begin() {
    Serial.println("Dashboard: initializing display with LGFX_AUTODETECT...");

    if (!display_.init()) {
        Serial.println("ERROR: display init failed");
    } else {
        Serial.println("Dashboard: display init OK");
    }

    // Backlight on GPIO 21, active HIGH.
    pinMode(GPIO_NUM_21, OUTPUT);
    digitalWrite(GPIO_NUM_21, HIGH);

    display_.setRotation(0); // Portrait 240x320
    display_.fillScreen(TFT_BLACK);
    display_.setTextDatum(middle_center);

    drawStatusBar_();
    for (size_t i = 0; i < 4; ++i) {
        int x = (i % 2) * 120;
        int y = 40 + (i / 2) * 110;
        drawProbeTile_(i, x, y, 120, 110);
    }
    drawFooter_("Touch here for settings");
}

void Dashboard::update(bool force) {
    if (!force && millis() - lastUpdateMillis_ < 1000) {
        return;
    }
    lastUpdateMillis_ = millis();

    ThermoproReading reading = bleClient_.getReading();
    char targetUnit = settings_.getUnit();

    if (force || reading.connected != lastBleConnected_ || reading.battery != lastBattery_) {
        lastBleConnected_ = reading.connected;
        lastBattery_ = reading.battery;
        drawStatusBar_();
    }

    for (size_t i = 0; i < 4; ++i) {
        float raw = reading.rawTemperatures[i];
        bool conn = isValidTemperature(raw);
        float displayTemp = conn ? convertTemperature(raw, reading.deviceUnit, targetUnit) : -9999.0f;

        if (force || conn != lastConnected_[i] || fabsf(displayTemp - lastTemps_[i]) > 0.05f) {
            lastConnected_[i] = conn;
            lastTemps_[i] = displayTemp;
            int x = (i % 2) * 120;
            int y = 40 + (i / 2) * 110;
            drawProbeTile_(i, x, y, 120, 110);
        }
    }

    String footer = "IP: " + WiFi.localIP().toString();
    if (WiFi.status() != WL_CONNECTED) {
        footer = "AP: CYD-ThermoPro-Setup";
    }
    drawFooter_(footer);
}

bool Dashboard::checkTouch() {
    uint16_t x, y;
    if (display_.getTouch(&x, &y)) {
        // The footer area is at the bottom 40 px of the screen in portrait mode.
        if (y > 280) {
            // Debounce: consume all touch events for 300 ms.
            unsigned long start = millis();
            while (display_.getTouch(&x, &y) && millis() - start < 300) {
                delay(10);
            }
            return true;
        }
    }
    return false;
}

void Dashboard::showMessage(const String& title, const String& line2, const String& line3) {
    display_.fillScreen(TFT_BLACK);
    display_.setTextColor(TFT_WHITE, TFT_BLACK);
    display_.setTextDatum(top_center);
    display_.setTextSize(2);
    display_.drawString(title.c_str(), display_.width() / 2, 60);

    display_.setTextSize(1);
    if (line2.length()) {
        display_.drawString(line2.c_str(), display_.width() / 2, 120);
    }
    if (line3.length()) {
        display_.drawString(line3.c_str(), display_.width() / 2, 150);
    }
    display_.setTextDatum(middle_center); // restore default
}

void Dashboard::drawStatusBar_() {
    int w = display_.width();
    display_.fillRect(0, 0, w, 36, TFT_DARKGREY);
    display_.drawLine(0, 36, w, 36, TFT_LIGHTGREY);

    ThermoproReading reading = bleClient_.getReading();

    // WiFi icon placeholder: small circle + text
    display_.setTextColor(TFT_WHITE, TFT_DARKGREY);
    display_.setTextDatum(middle_left);
    display_.setTextSize(1);
    display_.drawString("WiFi", 4, 18);

    String wifiStatus = (WiFi.status() == WL_CONNECTED) ? "OK" : "--";
    display_.drawString(wifiStatus.c_str(), 34, 18);

    // BLE status
    display_.setTextDatum(middle_right);
    String ble = reading.connected ? "BLE OK" : "BLE --";
    display_.drawString(ble.c_str(), w - 54, 18);

    // Battery
    String batt = String(reading.battery) + "%";
    display_.drawString(batt.c_str(), w - 4, 18);
}

void Dashboard::drawProbeTile_(size_t index, int x, int y, int tileW, int tileH) {
    ThermoproReading reading = bleClient_.getReading();
    char targetUnit = settings_.getUnit();
    float raw = reading.rawTemperatures[index];
    bool connected = isValidTemperature(raw);
    float temp = connected ? convertTemperature(raw, reading.deviceUnit, targetUnit) : -9999.0f;

    // Background
    uint16_t bgColor = (index % 2 == 0) ? TFT_DARKGREY : TFT_BLACK;
    display_.fillRect(x + 1, y + 1, tileW - 2, tileH - 2, bgColor);
    display_.drawRect(x, y, tileW, tileH, TFT_LIGHTGREY);

    // Probe name
    display_.setTextColor(TFT_WHITE, bgColor);
    display_.setTextDatum(top_center);
    display_.setTextSize(1);
    display_.drawString(settings_.getProbeName(index).c_str(), x + tileW / 2, y + 8);

    // Temperature
    display_.setTextSize(2);
    if (connected) {
        String t = formatTemperature_(temp);
        display_.drawString(t.c_str(), x + tileW / 2, y + tileH / 2 - 8);
        display_.setTextSize(1);
        display_.drawString((String("°") + targetUnit).c_str(), x + tileW / 2, y + tileH / 2 + 22);
    } else {
        display_.setTextColor(TFT_LIGHTGREY, bgColor);
        display_.drawString("---", x + tileW / 2, y + tileH / 2);
    }

    // Connection dot
    display_.fillCircle(x + tileW - 12, y + 12, 4, connected ? TFT_GREEN : TFT_RED);
}

void Dashboard::drawFooter_(const String& message) {
    int y = display_.height() - 40;
    display_.fillRect(0, y, display_.width(), 40, TFT_NAVY);
    display_.drawLine(0, y, display_.width(), y, TFT_LIGHTGREY);
    display_.setTextColor(TFT_WHITE, TFT_NAVY);
    display_.setTextDatum(middle_center);
    display_.setTextSize(1);
    display_.drawString(message.c_str(), display_.width() / 2, y + 20);
}

String Dashboard::formatTemperature_(float temp) {
    char buf[12];
    snprintf(buf, sizeof(buf), "%.1f", temp);
    return String(buf);
}

} // namespace cyd
