#pragma once

#include <QByteArray>
#include <QLocalSocket>
#include <QObject>
#include <QProcess>
#include <QTime>
#include <QTimer>
#include <qqmlintegration.h>
#include <qtmetamacros.h>

namespace ZShell::services {

class NightlightManager : public QObject {
	Q_OBJECT
	QML_ELEMENT
	Q_PROPERTY(bool enabled READ enabled NOTIFY enabledChanged)
	Q_PROPERTY(
		int startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged)
	Q_PROPERTY(int endTime READ endTime WRITE setEndTime NOTIFY endTimeChanged)
	Q_PROPERTY(int temp READ temp WRITE setTemp NOTIFY tempChanged)
	Q_PROPERTY(
		double fadeDuration READ fadeDuration WRITE setFadeDuration NOTIFY
			fadeDurationChanged)
	Q_PROPERTY(
		bool useNativeNightlight READ useNativeNightlight WRITE
			setUseNativeNightlight NOTIFY useNativeNightlightChanged)
	Q_PROPERTY(
		QString pluginPath READ pluginPath WRITE setPluginPath NOTIFY
			pluginPathChanged)
	Q_PROPERTY(
		bool activeAuto READ activeAuto WRITE setActiveAuto NOTIFY
			activeAutoChanged)
	Q_PROPERTY(
		bool manualToggle READ manualToggle WRITE setManualToggle NOTIFY
			manualToggleChanged)
	Q_PROPERTY(bool animating READ animating NOTIFY animatingChanged)
	Q_PROPERTY(int lastTemp READ lastTemp NOTIFY lastTempChanged)
	Q_PROPERTY(int currentTemp READ currentTemp NOTIFY currentTempChanged)

	public:
	explicit NightlightManager(QObject* parent = nullptr);

	[[nodiscard]] int startTime() const;
	[[nodiscard]] int endTime() const;
	[[nodiscard]] bool enabled() const;
	[[nodiscard]] int temp() const;
	[[nodiscard]] double fadeDuration() const;
	[[nodiscard]] bool useNativeNightlight() const;
	[[nodiscard]] QString pluginPath() const;
	[[nodiscard]] bool activeAuto() const;
	[[nodiscard]] bool manualToggle() const;
	[[nodiscard]] bool animating() const;
	[[nodiscard]] int lastTemp() const;
	[[nodiscard]] int currentTemp() const;

	Q_INVOKABLE void toggle();
	Q_INVOKABLE void apply();

	void setStartTime(const int& time);
	void setEndTime(const int& time);
	void setTemp(const int& temp);
	void setFadeDuration(double duration);
	void setUseNativeNightlight(bool native);
	void setPluginPath(const QString& path);
	void setActiveAuto(bool activeAuto);
	void setManualToggle(bool toggle);

	signals:
	void enabledChanged();
	void startTimeChanged();
	void activeAutoChanged();
	void endTimeChanged();
	void tempChanged();
	void fadeDurationChanged();
	void useNativeNightlightChanged();
	void pluginPathChanged();
	void manualToggleChanged();
	void animatingChanged();
	void lastTempChanged();
	void currentTempChanged();

	private:
	int m_startTime;
	int m_endTime;
	bool m_enabled = false;
	bool m_manualToggle = false;
	bool m_activeAuto;
	bool m_startAllowed = false;
	bool m_initialized = false;
	QTimer m_startCooldown;
	int m_temp;
	double m_fadeDuration = 0.4;
	bool m_useNativeNightlight = false;
	QString m_pluginPath;
	bool m_pluginLoadAttempted = false;
	bool m_pluginLoadedByUs = false;
	bool m_animating = false;
	int m_lastTemp = 6500;
	int m_currentTemp = 6500;
	QProcess m_process;
	QTimer m_timer;
	QTimer m_manualTimer;
	QLocalSocket m_eventSocket;
	QByteArray m_socketBuffer;
	QTimer m_reconnectTimer;

	void start();
	void end();
	[[nodiscard]] QString hyprlandDir() const;
	[[nodiscard]] QString eventSocketPath() const;
	[[nodiscard]] QString resolvePluginPath() const;
	void tryLoadPlugin();
	void bootstrapState();
	void connectEventSocket();
	void scheduleReconnect();
	void handleEventLines();
	void handleEventLine(const QByteArray& line);
	void updateState(bool enabled, bool animating, int last, int current);
};

}; // namespace ZShell::services
