#include <QSqlQuery>
#include <QSqlError>
#include "DeviceDAO.h"
#include "DatabaseManager.h"
#include "db/DeviceInfo.h"
#include "time/DateUtils.h"

DeviceInfo parseDevice(const QSqlQuery &query) {
    DeviceInfo device;
    device.id = query.value("id").toString();
    device.status = query.value("status").toString();
    device.name = query.value("name").toString();
    device.android = query.value("android").toString();
    device.screenWidth = query.value("screen_width").toInt();
    device.screenHeight = query.value("screen_height").toInt();
    device.battery = query.value("battery").toInt();
    device.updateTime = DateUtils::fromUtcString(query.value("update_time").toString());
    device.image = query.value("image").toByteArray();
    return device;
}

QList<DeviceInfo> DeviceDAO::getAllDevices(const bool online) {
    QList<DeviceInfo> devices;

    QSqlQuery query(DatabaseManager::instance().database());
    QString sql = R"(
        SELECT id, status, name, android, screen_width, screen_height, battery, update_time, image
        FROM devices
        WHERE image IS NOT NULL
    )";
    if (online) {
        sql += " AND status = 'device'";
    }
    query.prepare(sql);

    if (!query.exec()) {
        qWarning() << "Ошибка при получении списка устройств:" << query.lastError().text();
        return devices;
    }

    while (query.next()) {
        devices.append(parseDevice(query));
    }

    return devices;
}

QList<QString> DeviceDAO::getOnlineDeviceCodes() {
    QList<QString> codes;
    QSqlQuery query(DatabaseManager::instance().database());
    QString sql = R"(
        SELECT id
        FROM devices
        WHERE image IS NOT NULL AND status = 'device'
    )";
    query.prepare(sql);

    if (!query.exec()) {
        qWarning() << "Ошибка при получении списка устройств:" << query.lastError().text();
        return {};
    }

    while (query.next()) {
        codes.append(query.value("id").toString());
    }

    return codes;
}

DeviceInfo DeviceDAO::getDeviceById(const QString &deviceId) {
    QSqlQuery query(DatabaseManager::instance().database());

    query.prepare(R"(
        SELECT id, status, name, android, screen_width, screen_height, battery, update_time, image
        FROM devices
        WHERE id = :deviceId
    )");
    query.bindValue(":deviceId", deviceId);

    if (!query.exec()) {
        qWarning() << "Ошибка при получении устройства:" << query.lastError().text();
        return {};
    }

    while (query.next()) {
        return parseDevice(query);
    }

    return {};
}

bool DeviceDAO::upsertDevice(const DeviceInfo &device) {
    QSqlQuery query(DatabaseManager::instance().database());

    // Проверка: существует ли запись
    query.prepare("SELECT COUNT(*) FROM devices WHERE id = :id");
    query.bindValue(":id", device.id);

    if (!query.exec() || !query.next()) {
        qWarning() << "Ошибка при проверке существования записи:" << query.lastError().text();
        return false;
    }

    bool exists = query.value(0).toInt() > 0;

    if (exists) {
        // Обновление
        query.prepare(R"(
            UPDATE devices SET
                status = :status,
                name = :name,
                android = :android,
                screen_width = :width,
                screen_height = :height,
                battery = :battery,
                update_time = :update_time
            WHERE id = :id
        )");
    } else {
        // Вставка
        query.prepare(R"(
            INSERT INTO devices (
                id, status, name, android, screen_width, screen_height, battery, update_time
            ) VALUES (
                :id, :status, :name, :android, :width, :height, :battery, :update_time
            )
        )");
    }

    query.bindValue(":id", device.id);
    query.bindValue(":status", device.status);
    query.bindValue(":name", device.name);
    query.bindValue(":android", device.android);
    query.bindValue(":width", device.screenWidth);
    query.bindValue(":height", device.screenHeight);
    query.bindValue(":battery", device.battery);
    query.bindValue(":update_time", DateUtils::toUtcString(device.updateTime));

    if (!query.exec()) {
        qWarning() << "Ошибка при вставке/обновлении устройства:" << query.lastError().text();
        return false;
    }

    return true;
}

bool DeviceDAO::markDevicesOfflineExcept(const QStringList &onlineDeviceIds) {
    QSqlQuery query(DatabaseManager::instance().database());

    // Если список ID пуст, помечаем все как offline
    if (onlineDeviceIds.isEmpty()) {
        if (!query.exec("UPDATE devices SET status = 'offline'")) {
            qWarning() << "Ошибка при обновлении устройств на offline:" << query.lastError().text();
            return false;
        }
        return true;
    }

    // Генерируем плейсхолдеры :id0, :id1, ...
    QStringList placeholders;
    for (int i = 0; i < onlineDeviceIds.size(); ++i) {
        placeholders << QString(":id%1").arg(i);
    }

    const QString queryString = QString(
        "UPDATE devices SET status = 'offline' WHERE id NOT IN (%1)"
    ).arg(placeholders.join(", "));

    query.prepare(queryString);
    // Привязываем значения к плейсхолдерам
    for (int i = 0; i < onlineDeviceIds.size(); ++i) {
        query.bindValue(QString(":id%1").arg(i), onlineDeviceIds[i]);
    }

    if (!query.exec()) {
        qWarning() << "Ошибка при обновлении устройств на offline (исключая online):" << query.lastError().text();
        return false;
    }
    return true;
}

bool DeviceDAO::updateImage(const QString &deviceId, const QByteArray &imageData) {
    QSqlQuery query(DatabaseManager::instance().database());
    query.prepare("UPDATE devices SET image = :image WHERE id = :id");
    query.bindValue(":image", imageData);
    query.bindValue(":id", deviceId);

    if (!query.exec()) {
        qWarning() << "Ошибка при обновлении изображения:" << query.lastError().text();
        return false;
    }

    return true;
}
