#pragma once

#include <QObject>
#include <QTimer>
#include <QString>
#include <QVariantList>
#include <QtQml>

namespace ZShell::llm {

class LlmSegment : public QObject {
	Q_OBJECT
	QML_ELEMENT
	QML_UNCREATABLE("Segments are managed by ChatGeneration")

	Q_PROPERTY(Type type READ type CONSTANT)
	Q_PROPERTY(qint64 timestamp READ timestamp CONSTANT)
	Q_PROPERTY(QString text READ text NOTIFY textChanged)
	Q_PROPERTY(QString name READ name NOTIFY nameChanged)
	Q_PROPERTY(QString toolCallId READ toolCallId NOTIFY toolCallIdChanged)
	Q_PROPERTY(QString arguments READ arguments NOTIFY argumentsChanged)
	Q_PROPERTY(QString result READ result NOTIFY resultChanged)
	Q_PROPERTY(Status status READ status NOTIFY statusChanged)
	Q_PROPERTY(bool running READ running NOTIFY runningChanged)
	Q_PROPERTY(qint64 elapsedMs READ elapsedMs NOTIFY elapsedMsChanged)
	Q_PROPERTY(QVariantList markdown READ markdown NOTIFY markdownChanged)

	public:
	enum class Type : int { Reasoning = 0, ToolCall, Content };
	Q_ENUM(Type)

	// Pending is appended last: statuses are persisted as integers in the
	// chat database, so existing values must not move.
	enum class Status : int { None = 0, Running, Success, Error, Pending };
	Q_ENUM(Status)

	explicit LlmSegment(Type type, qint64 timestamp, QObject* parent = nullptr);

	[[nodiscard]] Type type() const { return m_type; }
	[[nodiscard]] qint64 timestamp() const { return m_timestamp; }
	[[nodiscard]] QString text() const { return m_text; }
	[[nodiscard]] QString name() const { return m_name; }
	[[nodiscard]] QString toolCallId() const { return m_toolCallId; }
	[[nodiscard]] QString arguments() const { return m_arguments; }
	[[nodiscard]] QString result() const { return m_result; }
	[[nodiscard]] Status status() const { return m_status; }
	[[nodiscard]] bool running() const { return m_running; }
	[[nodiscard]] qint64 elapsedMs() const;
	[[nodiscard]] QVariantList markdown() const { return m_markdown; }

	void begin();
	void close();
	void appendText(const QString& piece);
	void setText(const QString& value);
	void setName(const QString& value);
	void setToolCallId(const QString& value);
	void appendArguments(const QString& piece);
	void setResult(const QString& value);
	void setStatus(Status value);
	void finishTool(const QString& resultText, bool success);
	void restore(qint64 elapsedMs);

	Q_SIGNALS:
	void textChanged();
	void markdownChanged();
	void nameChanged();
	void toolCallIdChanged();
	void argumentsChanged();
	void resultChanged();
	void statusChanged();
	void runningChanged();
	void elapsedMsChanged();

	private:
	void scheduleMarkdown();
	bool parseMarkdown();

	Type m_type;
	qint64 m_timestamp;
	QString m_text;
	QString m_name;
	QString m_toolCallId;
	QString m_arguments;
	QString m_result;
	Status m_status = Status::None;
	bool m_running = false;
	qint64 m_startedAt = 0;
	qint64 m_endedAt = 0;
	QVariantList m_markdown;
	QTimer m_markdownTimer;
	bool m_markdownDirty = false;
	bool m_parseInFlight = false;
};

} // namespace ZShell::llm
