// SPDX-License-Identifier: GPL-3.0-or-later
// Extension : Gestionnaire de priorité et d'allocation de puissance énergétique

#ifndef ENERGYPRIORITYMANAGER_H
#define ENERGYPRIORITYMANAGER_H

#include <QObject>
#include <QList>
#include <QHash>
#include <QVariant>

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

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

// ─────────────────────────────────────────────────────────────
// Enums publics (sérialisés via JSON-RPC registerEnum)
// ─────────────────────────────────────────────────────────────

class EnergyPriorityManager : public QObject
{
    Q_OBJECT
public:

    /// Priorité d'une charge — détermine qui est servi en premier
    /// en cas de puissance limitée.
    enum LoadPriority {
        LoadPriorityCritical  = 0,  // Ne jamais couper (ex: chauffage hiver)
        LoadPriorityHigh      = 1,  // Couper seulement en dernier recours
        LoadPriorityNormal    = 2,  // Comportement standard
        LoadPriorityLow       = 3,  // Interruptible (ex: recharge VE, ECS boost)
        LoadPriorityOptional  = 4   // Seulement avec surplus solaire
    };
    Q_ENUM(LoadPriority)

    /// Type de charge gérable
    enum LoadType {
        LoadTypeEvCharger,
        LoadTypeHeatPump,
        LoadTypeDHW,
        LoadTypeUnknown
    };
    Q_ENUM(LoadType)

    // ─── Structure représentant une charge gérée ──────────────

    struct ManagedLoad {
        ThingId thingId;
        QString name;
        LoadType type;
        LoadPriority priority;
        double allocatedPower;    // Watts — puissance actuellement allouée
        double requestedPower;    // Watts — puissance demandée par la charge
        double currentPower;      // Watts — puissance mesurée en temps réel
        bool   active;            // Charge actuellement autorisée à consommer
    };

    explicit EnergyPriorityManager(EnergyManager *energyManager,
                                   ThingManager *thingManager,
                                   QObject *parent = nullptr);

    // ─── Gestion des charges ─────────────────────────────────

    void registerLoad(const ThingId &thingId, LoadType type,
                      LoadPriority priority = LoadPriorityNormal);
    void unregisterLoad(const ThingId &thingId);

    QList<ManagedLoad> managedLoads() const;
    ManagedLoad managedLoad(const ThingId &thingId) const;

    // ─── Limites globales ────────────────────────────────────

    double totalAvailablePower() const;
    void setTotalAvailablePower(double watts);

    double reservedPowerForCritical() const;
    void setReservedPowerForCritical(double watts);

    // ─── Priorités ───────────────────────────────────────────

    EnergyManager::EnergyError setLoadPriority(const ThingId &thingId,
                                               LoadPriority priority);

    EnergyManager::EnergyError setAllocatedPower(const ThingId &thingId,
                                                  double watts);

    // ─── Allocation automatique ──────────────────────────────

    /// Recalcule et applique l'allocation de puissance à toutes les charges
    /// selon leur priorité et la puissance disponible.
    void rebalance();

signals:
    void managedLoadAdded(const ThingId &thingId);
    void managedLoadRemoved(const ThingId &thingId);
    void managedLoadChanged(const ThingId &thingId);
    void totalAvailablePowerChanged(double watts);

private:
    void updateLoadCurrentPower(const ThingId &thingId, double watts);

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

    QHash<ThingId, ManagedLoad> m_loads;
    double m_totalAvailablePower = 11000.0;  // 3 x 16A x 230V par défaut
    double m_reservedForCritical = 3000.0;   // 3kW réservé pour les critiques
};

#endif // ENERGYPRIORITYMANAGER_H
