#pragma once

#include "session.hpp"

#include <QObject>
#include <QSet>
#include <QSqlDatabase>
#include <QString>
#include <QVariantList>

namespace ZShell::llm {

class LlmClient;

class ChatStore : public QObject {
	Q_OBJECT
	QML_ANONYMOUS

	Q_PROPERTY(int count READ count NOTIFY countChanged)
	Q_PROPERTY(QVariantList values READ values NOTIFY valuesChanged)

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

	[[nodiscard]] int count() const;
	[[nodiscard]] QVariantList values() const;
	[[nodiscard]] ChatSession* at(int index) const;

	Q_INVOKABLE ZShell::llm::ChatSession* insert(int index = -1);
	Q_INVOKABLE void remove(int index);
	Q_INVOKABLE void remove(ZShell::llm::ChatSession* chat);
	Q_INVOKABLE void move(int from, int to);
	Q_INVOKABLE void clear();

	[[nodiscard]] ChatSession* sessionById(const QString& id);
	[[nodiscard]] LlmClient* llmClient() const { return m_llmClient; }
	void setLlmClient(LlmClient* client);

	void persist(ChatSession* session);
	void saveMeta(ChatSession* session);
	void loadMessagesInto(ChatSession* session);

	Q_SIGNALS:
	void countChanged();
	void valuesChanged();
	void sessionRemoved(ZShell::llm::ChatSession* session);

	private:
	void openDb();
	void load();
	bool saveSession(ChatSession* session);
	void sortAndNotify();
	void removeSession(ChatSession* session);
	void notify(const QList<ChatSession*>& before);

	QList<ChatSession*> m_sessions;
	LlmClient* m_llmClient = nullptr;
	QString m_connectionName;
	QString m_dbPath;
	QSet<ChatSession*> m_pendingPersists;

	[[nodiscard]] QSqlDatabase db() const;
};

} // namespace ZShell::llm
