// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (C) 2025 - 2026, Patrick Schurig / ETM PowerSync
#pragma once

#include <QDateTime>
#include <QList>
#include <QString>
#include "loadaction.h"

/*!
 * \brief Capacités déclarées par l'installateur (plaque signalétique, câblage).
 * Correspond à OPTIMIZER_PROTOCOL.md §5 loads[].declared (noms identiques).
 * \note Les champs inutilisés pour un type d'adaptateur restent à leur valeur par défaut.
 */
struct LoadDeclared {
    // --- evcharger ---
    double minA   = 0;  //!< Courant minimum (A).
    double maxA   = 0;  //!< Courant maximum (A).
    int    phases = 0;  //!< Nombre de phases disponibles (1 ou 3).

    // --- relay-stages (ECS) ---
    //! Puissances en W par palier : [0, 1200, 2400] — index 0 = off.
    QList<int> stages;

    // --- battery ---
    double maxChargeW        = 0;  //!< Puissance max de charge (W).
    double maxDischargeW     = 0;  //!< Puissance max de décharge (W).
    double capacityWh        = 0;  //!< Capacité totale (Wh).
    int    reserveSocPercent = 0;  //!< SOC de réserve (%) — non déchargeable.

    // sg-ready : états toujours 1-4, pas de déclaration nécessaire.
};

/*!
 * \brief Contraintes anti-rebond et lock temporel d'une charge.
 * Correspond à OPTIMIZER_PROTOCOL.md §5 loads[].limits.
 */
struct LoadLimits {
    int minOnS               = 0;  //!< Durée minimale ON (s).
    int minOffS              = 0;  //!< Durée minimale OFF (s).
    int chargingEnabledLockS = 0;  //!< Lock on/off (s) — evcharger.
    int currentChangeLockS   = 0;  //!< Lock changement courant (s) — evcharger.
    int minStateHoldS        = 0;  //!< Durée minimale maintien état (s) — sg-ready.
};

/*!
 * \brief Besoins énergétiques déclarés par l'utilisateur pour une charge.
 * Correspond à OPTIMIZER_PROTOCOL.md §5 loads[].needs.
 */
struct LoadNeeds {
    int       targetSocPercent  = 0;    //!< SOC cible (%) — EV / batterie.
    QDateTime deadline;                  //!< Échéance absolue de recharge.
    QString   dailyDeadline;             //!< Heure limite quotidienne, format "HH:MM".
    int       minEnergyWhPerDay = 0;     //!< Énergie minimale par jour (Wh).
};

/*!
 * \brief Description statique complète d'une charge, exposée par ILoadAdapter.
 *
 * L'arbitre lit ce descripteur une fois par cycle pour construire le SurplusContext.
 * Les valeurs doivent refléter la configuration matérielle réelle (non les setpoints).
 *
 * \note \c priority : rang dans la liste ordonnée du client (OPTIMIZER_PROTOCOL §5 +
 *   annexe C). Valeur plus BASSE = servi en premier (rang 1 = premier servi).
 *   Les promotions conditionnelles (deadline, Tempo ROUGE) sont gérées par le scheduler,
 *   pas par un poids numérique.
 */
struct LoadDescriptor {
    QString                  id;       //!< ThingId de la charge (string).
    QString                  label;    //!< Nom lisible (affiché dans les logs).
    //! Type d'adaptateur : "evcharger"|"relay-stages"|"sg-ready"|"battery".
    QString                  adapter;
    int                      priority = 0;
    LoadDeclared             declared;
    LoadLimits               limits;
    LoadNeeds                needs;
    QList<LoadAction::Kind>  supportedKinds;  //!< Kinds acceptés par applyAction().
};
