// 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"

// Structures miroirs de OPTIMIZER_PROTOCOL.md §6 (noms de champs identiques).

/*!
 * \brief Créneau d'un plan — contient les LoadAction à appliquer pendant [from, to[.
 *
 * \invariant Les actions sont ordonnées par priorité croissante (rang 1 = premier servi,
 *   OPTIMIZER_PROTOCOL §5 + annexe C).
 * \invariant Un Slot vide (actions vide) est valide — signifie "aucune action ce créneau".
 */
struct Slot {
    QDateTime         from;
    QDateTime         to;
    QList<LoadAction> actions;
};

/*!
 * \brief Plan d'optimisation retourné par IScheduler::getPlan().
 *
 * \invariant \c isValid() == true après tout appel à getPlan() (invariant IScheduler).
 * \invariant \c planId est unique par plan généré (UUID ou compteur).
 */
struct Plan {
    QString      planId;    //!< Identifiant unique (UUID string).
    QString      strategy;  //!< "rule-based" | "socket" | "socket-fallback".
    //! Créneaux du plan. Nommé \c timeSlots (pas \c slots, mot-clé Qt).
    //! Sérialisation JSON : sous le nom "slots" — OPTIMIZER_PROTOCOL.md §6
    //! fait autorité sur le nom de fil, le renommage est purement interne C++.
    QList<Slot>  timeSlots;

    /*!
     * \brief Retourne le Slot couvrant \p dt.
     * \param dt Instant à couvrir.
     * \return Slot dont from ≤ dt < to, ou Slot vide (from/to invalides) si aucun ne correspond.
     */
    Slot slotCovering(const QDateTime &dt) const {
        for (const Slot &s : timeSlots) {
            if (dt >= s.from && dt < s.to)
                return s;
        }
        return {};
    }

    /*! \brief Vrai si le plan contient au moins un Slot. */
    bool isValid() const { return !timeSlots.isEmpty(); }
};
