#pragma once

#include "message.hpp"

#include <QAbstractListModel>
#include <QHash>
#include <QList>
#include <QtQml>
#include <qtmetamacros.h>

namespace ZShell::llm {

class ChatSession;

class ChatMessageModel : public QAbstractListModel {
	Q_OBJECT
	QML_ELEMENT
	QML_UNCREATABLE("Chat message models are owned by ChatSession")

	Q_PROPERTY(
		ZShell::llm::ChatMessage* lastMessage READ lastMessage NOTIFY
			lastMessageChanged)

	public:
	explicit ChatMessageModel(ChatSession* session, QObject* parent = nullptr);
	~ChatMessageModel() override;

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

	[[nodiscard]] ChatSession* session() const { return m_session; }
	[[nodiscard]] QList<ChatMessage*> messages() const { return m_messages; }
	[[nodiscard]] ChatMessage* at(int row) const;
	[[nodiscard]] int rowOf(const ChatMessage* message) const;

	[[nodiscard]] ChatMessage* lastMessage() const {
		return m_messages.isEmpty() ? nullptr : m_messages.first();
	}

	ChatMessage* createMessage(ChatMessage::Role role, qint64 timestamp);
	ChatMessage* appendNewest(
		ChatMessage::Role role, const QString& content, qint64 timestamp);
	void removeMessage(ChatMessage* message);
	void removeRange(int firstRow, int lastRow);
	void clear();
	void loadMessages(QList<ChatMessage*> messages);

	signals:
	void lastMessageChanged();

	private:
	ChatSession* m_session;
	QList<ChatMessage*> m_messages;
};

} // namespace ZShell::llm
