// devicediscovery.h
#ifndef DEVICE_DISCOVERY_H
#define DEVICE_DISCOVERY_H

#include <QAbstractListModel>
#include <QNetworkAccessManager>
#include <QTimer>
#include <QUdpSocket>
#include <QHostInfo>
#include <QFuture>
#include <tuple>
#include "stellarmatedevice.h"
#include "qmdns.h" // Include qMDNS header

class DeviceDiscovery : public QAbstractListModel
{
        Q_OBJECT
        Q_PROPERTY(bool isScanning READ isScanning NOTIFY isScanningChanged)
        Q_PROPERTY(QString statusText READ statusText NOTIFY statusTextChanged)
        Q_PROPERTY(int deviceCount READ deviceCount NOTIFY deviceCountChanged)
        Q_PROPERTY(bool hasWifiDongle READ hasWifiDongle NOTIFY wifiDongleStatusChanged)
        Q_PROPERTY(bool useInternalWifi READ useInternalWifi WRITE setUseInternalWifi NOTIFY hotspotInterfaceChanged)

    public:
        explicit DeviceDiscovery(QObject *parent = nullptr);
        ~DeviceDiscovery() override;

        static void setVerbose(bool verbose);
        static bool isVerbose();

        struct RefreshOperation
        {
            QTimer* timeoutTimer;
            int hostnameReceived = 0;
            int versionReceived = 0;
            int modelReceived = 0;
        };

        QMap<QString, RefreshOperation> m_activeRefreshes;
        void checkRefreshCompletion(const QString &ipAddress);

        Q_INVOKABLE void applyDeltaUpdate(int deviceIndex, const QString &targetVersion);
        Q_INVOKABLE void checkDeltaProgress(int deviceIndex);
        Q_INVOKABLE void checkDeltaStatus(int deviceIndex);

        enum Roles
        {
            IpAddressRole = Qt::UserRole + 1,
            HostnameRole,
            VersionRole,
            ModelRole,
            IsOnlineRole,
            IsLocalRole,
            StatusTextRole,
            SecondaryIpsRole
        };
        Q_ENUM(Roles)

        int rowCount(const QModelIndex &parent = QModelIndex()) const override;
        QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
        QHash<int, QByteArray> roleNames() const override;

        bool isScanning() const
        {
            return m_isScanning;
        }
        QString statusText() const
        {
            return m_statusText;
        }
        int deviceCount() const
        {
            return m_devices.size();
        }
        bool hasWifiDongle() const
        {
            return m_hasWifiDongle;
        }
        bool useInternalWifi() const
        {
            return m_useInternalWifi;
        }
        void setUseInternalWifi(bool useInternal);

    public slots:
        void startDiscovery();
        void stopDiscovery();
        void queryExternalStorage(int deviceIndex);
        void addManualDevice(const QString &ipAddress);
        void removeDevice(int index);
        void refreshDevice(int index);
        void refreshAllDevices();
        void updateDeviceHostname(int index, const QString &newHostname);
        void applyRollback(int deviceIndex, const QString &targetVersion);


        // Pictures directory methods
        void queryPicturesDirectory(int deviceIndex);
        void updatePicturesDirectory(int deviceIndex, const QString &newDirectory);
        void resetEkosLive(int deviceIndex);
        void checkEkosLiveRegenerationProgress(int deviceIndex);
        void queryHotspotInterface(int deviceIndex);
        void updateHotspotInterface(int deviceIndex, bool useInternalWifi);
        void queryNetworkInterfaces(int deviceIndex);

        // System control methods
        void networkReset(int deviceIndex);

        void startPeriodicStatusUpdates();
        void stopPeriodicStatusUpdates();
        void onPeriodicStatusUpdate();
        void queryDeviceStatus(const QString &ipAdress);

        // Web interface and remote access methods
        void openStellarMateWebUI(int deviceIndex);
        void openCustomPort(int deviceIndex, int port);
        void openVNCViewer(int deviceIndex);

        void reboot(int deviceIndex);
        void shutdown(int deviceIndex);
        void factoryReset(int deviceIndex);
        void checkForSoftwareUpdates(int deviceIndex);
        void startSoftwareUpdate(int deviceIndex);
        void checkSoftwareUpdateProgress(int deviceIndex);

        // Ethernet control methods
        void activateDirectEthernet(int deviceIndex);
        void deactivateDirectEthernet(int deviceIndex);

    signals:
        void isScanningChanged();
        void statusTextChanged();
        void deviceCountChanged();
        void deviceAdded(const QString &ipAddress);
        void deviceRemoved(const QString &ipAddress);
        void hostnameUpdated(const QString &ipAddress, bool success, const QString &message);
        void wifiDongleStatusChanged();
        void hotspotInterfaceChanged();
        void hotspotInterfaceReceived(const QString &ipAddress, bool useInternalWifi);
        void hotspotInterfaceUpdated(const QString &ipAddress, bool success, const QString &message);
        void networkInterfacesReceived(const QString &ipAddress, const QVariantMap &interfaces);
        void softwareUpdateCheckCompleted(const QString &ipAddress, bool success, bool isUpgradable,
                                          const QString &message, bool hasDelta, const QVariantMap &deltaMetadata);
        void deviceBackOnline(const QString &ipAddress);
        void rollbackApplyCompleted(const QString &ipAddress, bool success, const QString &message);
        void softwareUpdateStarted(const QString &ipAddress, bool success, const QString &message);
        void softwareUpdateProgressReceived(const QString &ipAddress, double progress);
        void softwareUpdateTimedOut(const QString &ipAddress);
        void externalStorageReceived(const QString &ipAddress, const QStringList &devices);

        // Pictures directory signals
        void picturesDirectoryReceived(const QString &ipAddress, const QString &directory);
        void picturesDirectoryUpdated(const QString &ipAddress, bool success, const QString &message);

        // System control signals
        void networkResetCompleted(const QString &ipAddress, bool success, const QString &message);

        void ekosLiveResetCompleted(const QString &ipAddress, bool success, const QString &message);
        void ekosLiveRegenerationProgressReceived(const QString &ipAddress, int progress, const QString &message, bool inProgress);
        void rebootCompleted(const QString &ipAddress, bool success, const QString &message);
        void shutdownCompleted(const QString &ipAddress, bool success, const QString &message);
        void factoryResetCompleted(const QString &ipAddress, bool success, const QString &message);

        // Ethernet control signals
        void ethernetActivationCompleted(const QString &ipAddress, bool success, const QString &message);
        void ethernetDeactivationCompleted(const QString &ipAddress, bool success, const QString &message);

        void deltaUpdateCheckCompleted(const QString &ipAddress, bool available, const QVariantMap &metadata);
        void deltaUpdateStarted(const QString &ipAddress, bool success, const QString &message);
        void deltaUpdateProgressReceived(const QString &ipAddress, int progress, const QString &message);
        void deltaStatusReceived(const QString &ipAddress, bool pendingReboot, const QString &state);



    private slots:
        void onNetworkReplyFinished();
        void onDiscoveryTimeout();
        void onMdnsHostFound(const QHostInfo &hostInfo);
        void onMdnsTimeout();
        void onMdnsServiceFound(const QString &serviceType, const QString &serviceName, const QString &host,
                                const QHostAddress &address, quint16 port, const QMap<QString, QString> &txtRecords);

    private:
        void queryDeviceInfo(const QString &ipAddress);
        void addOrUpdateDevice(const StellarMateDevice &device);
        void startMdnsDiscovery();
        void startNetworkScan();
        void setScanning(bool scanning);
        void setStatusText(const QString &text);
        void checkMdnsCompletion();
        void triggerEkosLiveImageRegeneration(const QString &ipAddress);
        bool m_hasWifiDongle;
        bool m_useInternalWifi;
        QMap<QString, bool> m_deviceWifiDongles;
        QMap<QString, bool> m_deviceHotspotSettings;

        QNetworkAccessManager *m_networkManager;
        QTimer *m_discoveryTimer;
        QTimer *m_mdnsTimer;
        QTimer *m_statusUpdateTimer;
        QUdpSocket *m_udpSocket;
        qMDNS *m_mdns;
        bool m_isScanning;
        bool m_mdnsPhase;
        QString m_statusText;
        QList<StellarMateDevice> m_devices;
        QMap<QString, StellarMateDevice> m_tempDevices;
        QMap<QString, std::tuple<bool, bool, bool, bool>> m_deviceInfoStatus;
        QMap<QString, qint64> m_lastStatusUpdate;
        QStringList m_mdnsFoundIps;
        int m_pendingRequests;
        int m_mdnsDevicesFound;

        // Pictures directory storage
        QMap<QString, QString> m_picturesDirectories;
        QNetworkAccessManager *networkManager;
        QMap<QString, QTimer *> softwareUpdateTimers;
        bool m_initialDeviceListWasEmpty;

        // mDNS async initialization flags
        bool m_mdnsInitialized;
        bool m_pendingStartDiscovery;
        QFuture<void> m_mdnsInitFuture;

        static bool s_verbose; // Flag to control verbose debug logging
};

#endif // DEVICE_DISCOVERY_H
