// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef INTEGRATIONPLUGINV2C_H
#define INTEGRATIONPLUGINV2C_H

#include <plugintimer.h>
#include <integrations/integrationplugin.h>

#include "extern-plugininfo.h"
#include "trydanmodbusmaster.h"
#include "trydanmodbustcpmaster.h"

/*!
 * \brief nymea integration plugin for the V2C Trydan EV charger.
 *
 * ThingClass \c trydan implementing the \c evcharger interface via Modbus TCP
 * (Étape 1).  All register-level I/O is delegated to TrydanModbusTcpMaster;
 * this class owns the evcharger business logic:
 *  - ChargeState → pluggedIn / charging mapping
 *  - chargingEnabled = (PauseState==0 AND Lock==0)
 *  - Dynamic optimizer conflict management via PauseDynamic
 *
 * No NetworkDeviceMonitor: the Trydan ESP32 WiFi stack saturates under
 * periodic ICMP pings (latency > 14 s, Modbus timeouts).  Connectivity is
 * derived from Modbus poll success/failure instead.
 *
 * Étape 2 (RTU) will add TrydanModbusRtuMaster on the same TrydanModbusMaster
 * interface; the logic in this file requires no changes.
 */
class IntegrationPluginV2c : public IntegrationPlugin
{
    Q_OBJECT

    Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginv2c.json")
    Q_INTERFACES(IntegrationPlugin)

public:
    explicit IntegrationPluginV2c();

    void discoverThings(ThingDiscoveryInfo *info) override;
    void setupThing(ThingSetupInfo *info)          override;
    void postSetupThing(Thing *thing)              override;
    void thingRemoved(Thing *thing)                override;

public slots:
    void executeAction(ThingActionInfo *info) override;

private:
    /*! \brief Apply all evcharger states from the last completed poll. */
    void updateThingStates(Thing *thing, TrydanModbusMaster *master);

    /*!
     * \brief Manage the Dynamic/PauseDynamic conflict on each poll.
     *
     * If Dynamic==1 (V2C internal optimizer is running) and HEMS is in control
     * (chargingEnabled==true), write PauseDynamic=1 to suppress the internal PID
     * without disabling the telemetry.  Release PauseDynamic=0 when HEMS
     * relinquishes control.  Dynamic is NEVER written (would silence ChargePower).
     * cf. AGENTS.md § CONFLIT and evcc charger/trydan.go.
     */
    void handleDynamicConflict(Thing *thing, TrydanModbusMaster *master);

    void setDisconnectedState(Thing *thing, const QString &cause = QString());

    PluginTimer *m_pluginTimer = nullptr;

    QHash<Thing *, TrydanModbusTcpMaster *> m_tcpMasters;
};

#endif // INTEGRATIONPLUGINV2C_H
