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

#include <QString>

/*!
 * \brief Action typée émise par l'arbitre vers un ILoadAdapter.
 *
 * Noms de champs identiques à OPTIMIZER_PROTOCOL.md §6 (fait autorité).
 * \c funding est interne à l'arbitre — absent du JSON protocole socket.
 *
 * \invariant \c reason doit être non vide et en français (AGENTS invariant 7).
 *   Un adaptateur doit rejeter toute action avec \c reason vide.
 * \invariant Pour kind == Setpoint / evcharger : seuls \c chargingEnabled,
 *   \c currentA, \c phaseCount sont significatifs.
 */
struct LoadAction {
    /*! \brief Type d'action : consigne continue, palier discret, état ou contrainte. */
    enum Kind       { Setpoint, Stage, State, Constraint };
    /*! \brief Financement interne : Surplus (PV) ou Grid (réseau). Non sérialisé. */
    enum Funding    { Surplus, Grid };
    /*! \brief Source d'énergie pour Setpoint batterie : "solar" ou "grid". */
    enum Source     { Solar, GridSource };
    /*! \brief Permission de charge/décharge pour Constraint batterie. */
    enum Permission { Allow, Forbid };

    QString  loadId;            //!< ThingId de la charge cible (string).
    Kind     kind    = Setpoint;
    Funding  funding = Surplus;

    // --- Setpoint evcharger ---
    bool     chargingEnabled = false;
    double   currentA        = 0;   //!< Courant consigne (A), écrêté par l'adaptateur.
    uint     phaseCount      = 0;   //!< Nombre de phases (1 ou 3, 0 = inchangé).

    // --- Setpoint battery ---
    double   powerW  = 0;
    Source   source  = Solar;

    // --- Stage relay-stages (ECS) ---
    int      stage   = 0;           //!< Index de palier (0 = off, 1 = 1er palier, ...).

    // --- State sg-ready ---
    int      state   = 0;           //!< État SG-Ready (1-4).

    // --- Constraint battery ---
    Permission charge    = Allow;
    Permission discharge = Allow;

    /*!
     * \brief Motif de la décision, non vide, en français.
     * Obligatoire (invariant 7). L'adaptateur rejette silencieusement si vide.
     */
    QString reason;

    /*!
     * \brief Puissance estimée (W) — hint pour la comptabilité budget de l'arbitre.
     * Rempli par le scheduler ; peut être 0 si inconnu.
     */
    double estimatedPowerW = 0;

    /*!
     * \brief Forçage sécurité — bypasse les verrous anti-rebond (minOn/minOff).
     *
     * Positionné à \c true uniquement par \c applyDegradedMode() (L2 watchdog)
     * et les contraintes de sécurité. Les adaptateurs doivent appliquer l'action
     * immédiatement sans vérifier les verrous temporels.
     * \warning Réservé à la sécurité. Ne jamais mettre à \c true dans un scheduler.
     */
    bool force = false;
};
