// SPDX-License-Identifier: GPL-3.0-or-later
// Extension : Gestionnaire Pompe à chaleur + ECS pour nymea-energy-plugin-nymea

#ifndef HEATPUMPMANAGER_H
#define HEATPUMPMANAGER_H

#include <QObject>
#include <QHash>
#include <QTimer>

// from libnymea
#include <integrations/thingmanager.h>
#include <integrations/thing.h>

// from libnymea-energy
#include <energymanager.h>

// ─── UUIDs ThingClass ────────────────────────────────────────
// Ces UUIDs doivent correspondre aux entrées dans le fichier JSON
// du plugin d'intégration ETM.

static const QUuid kHeatPumpThingClassId     = QUuid("b5a8f3d2-4c1e-4a9f-8b2d-3e6c0f1d5a7b");
static const QUuid kDomesticHotWaterClassId  = QUuid("c7d2e4f1-5b3a-4c0d-9e6f-2a4b7c1d3e5f");

// ─── UUIDs StateTypes — Heat Pump ───────────────────────────
static const QUuid kHPStatePower             = QUuid("d4e5f6a7-b8c9-4d0e-1f2a-3b4c5d6e7f8a");
static const QUuid kHPStateMode              = QUuid("e5f6a7b8-c9d0-4e1f-2a3b-4c5d6e7f8a9b");
static const QUuid kHPStateTargetTemperature = QUuid("f6a7b8c9-d0e1-4f2a-3b4c-5d6e7f8a9b0c");
static const QUuid kHPStateCurrentTemp       = QUuid("a7b8c9d0-e1f2-4a3b-4c5d-6e7f8a9b0c1d");
static const QUuid kHPStateCurrentPower      = QUuid("c9d0e1f2-a3b4-4c5d-6e7f-8a9b0c1d2e3f");
static const QUuid kHPStateCop               = QUuid("d0e1f2a3-b4c5-4d6e-7f8a-9b0c1d2e3f4a");
static const QUuid kHPStateDefrostActive     = QUuid("e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b");

// ─── UUIDs ActionTypes — Heat Pump ──────────────────────────
static const QUuid kHPActionSetMode              = QUuid("a3b4c5d6-e7f8-4a9b-0c1d-2e3f4a5b6c7d");
static const QUuid kHPActionSetTargetTemperature = QUuid("c5d6e7f8-a9b0-4c1d-2e3f-4a5b6c7d8e9f");
static const QUuid kHPActionParamMode            = QUuid("b4c5d6e7-f8a9-4b0c-1d2e-3f4a5b6c7d8e");
static const QUuid kHPActionParamTargetTemp      = QUuid("d6e7f8a9-b0c1-4d2e-3f4a-5b6c7d8e9f0a");

// ─── UUIDs StateTypes — DHW ─────────────────────────────────
static const QUuid kDHWStatePower             = QUuid("d2e3f4a5-b6c7-4d8e-9f0a-1b2c3d4e5f6a");
static const QUuid kDHWStateTargetTemperature = QUuid("e3f4a5b6-c7d8-4e9f-0a1b-2c3d4e5f6a7b");
static const QUuid kDHWStateCurrentTemp       = QUuid("f4a5b6c7-d8e9-4f0a-1b2c-3d4e5f6a7b8c");
static const QUuid kDHWStateBoostMode         = QUuid("a5b6c7d8-e9f0-4a1b-2c3d-4e5f6a7b8c9d");
static const QUuid kDHWStateCurrentPower      = QUuid("b6c7d8e9-f0a1-4b2c-3d4e-5f6a7b8c9d0e");

// ─── UUIDs ActionTypes — DHW ────────────────────────────────
static const QUuid kDHWActionTriggerBoost     = QUuid("d8e9f0a1-b2c3-4d4e-5f6a-7b8c9d0e1f2a");
static const QUuid kDHWActionParamDuration    = QUuid("e9f0a1b2-c3d4-4e5f-6a7b-8c9d0e1f2a3b");

// ─────────────────────────────────────────────────────────────

class HeatPumpDevice;
class DomesticHotWaterDevice;

class HeatPumpManager : public QObject
{
    Q_OBJECT
public:
    explicit HeatPumpManager(EnergyManager *energyManager,
                             ThingManager *thingManager,
                             QObject *parent = nullptr);

    // ─── Heat Pump ───────────────────────────────────────────

    /// Retourne tous les appareils PAC connus
    QList<HeatPumpDevice *> heatPumps() const;

    /// Allume/éteint une PAC
    EnergyManager::EnergyError setPower(const ThingId &thingId, bool on);

    /// Change le mode (heating / cooling / auto / standby)
    EnergyManager::EnergyError setMode(const ThingId &thingId, const QString &mode);

    /// Définit la température cible [15–65 °C]
    EnergyManager::EnergyError setTargetTemperature(const ThingId &thingId, double temperature);

    // ─── Domestic Hot Water ──────────────────────────────────

    QList<DomesticHotWaterDevice *> dhwDevices() const;

    EnergyManager::EnergyError setDHWPower(const ThingId &thingId, bool on);
    EnergyManager::EnergyError setDHWTargetTemperature(const ThingId &thingId, double temperature);
    EnergyManager::EnergyError triggerDHWBoost(const ThingId &thingId, uint durationMinutes = 30);

    // ─── Gestion énergie ─────────────────────────────────────

    /// Puissance totale consommée par toutes les PAC + ECS
    double totalThermalPower() const;

signals:
    void heatPumpAdded(const ThingId &thingId);
    void heatPumpRemoved(const ThingId &thingId);
    void heatPumpStateChanged(const ThingId &thingId, const QString &stateName, const QVariant &value);

    void dhwDeviceAdded(const ThingId &thingId);
    void dhwDeviceRemoved(const ThingId &thingId);
    void dhwStateChanged(const ThingId &thingId, const QString &stateName, const QVariant &value);

private slots:
    void onThingAdded(Thing *thing);
    void onThingRemoved(const ThingId &thingId);
    void onThingStateChanged(Thing *thing, const StateType &stateType, const QVariant &value, const QVariant &minValue, const QVariant &maxValue);

private:
    void setupHeatPump(Thing *thing);
    void setupDHWDevice(Thing *thing);

    EnergyManager *m_energyManager = nullptr;
    ThingManager *m_thingManager = nullptr;

    QHash<ThingId, HeatPumpDevice *> m_heatPumps;
    QHash<ThingId, DomesticHotWaterDevice *> m_dhwDevices;
};

// ─────────────────────────────────────────────────────────────
// Wrappers de Thing
// ─────────────────────────────────────────────────────────────

class HeatPumpDevice : public QObject
{
    Q_OBJECT
public:
    explicit HeatPumpDevice(Thing *thing, QObject *parent = nullptr);

    ThingId id() const;
    QString name() const;
    Thing *thing() const;

    bool power() const;
    QString mode() const;      // "heating" | "cooling" | "auto" | "standby"
    double targetTemperature() const;
    double currentTemperature() const;
    double currentPower() const;
    double cop() const;
    bool defrostActive() const;

signals:
    void powerChanged(bool power);
    void modeChanged(const QString &mode);
    void targetTemperatureChanged(double temperature);
    void currentTemperatureChanged(double temperature);
    void currentPowerChanged(double power);
    void copChanged(double cop);

private:
    Thing *m_thing = nullptr;
};

class DomesticHotWaterDevice : public QObject
{
    Q_OBJECT
public:
    explicit DomesticHotWaterDevice(Thing *thing, QObject *parent = nullptr);

    ThingId id() const;
    QString name() const;
    Thing *thing() const;

    bool power() const;
    double targetTemperature() const;
    double currentTemperature() const;
    bool boostMode() const;
    double currentPower() const;

signals:
    void powerChanged(bool power);
    void targetTemperatureChanged(double temperature);
    void currentTemperatureChanged(double temperature);
    void boostModeChanged(bool active);
    void currentPowerChanged(double power);

private:
    Thing *m_thing = nullptr;
};

#endif // HEATPUMPMANAGER_H
