#pragma once

#include "tool.hpp"

#include <QByteArray>
#include <QList>
#include <QNetworkAccessManager>

#include <functional>

class QNetworkReply;
class QTimer;

namespace ZShell::llm {

class WebFetchTool : public LlmTool {
	Q_OBJECT

	public:
	static constexpr int MaxResponseBytes = 5 * 1024 * 1024;
	static constexpr int DefaultTimeoutSeconds = 30;
	static constexpr int MaxTimeoutSeconds = 120;
	// Where the full (untruncated) output of each call is stored so the
	// model can page through it with the readfile tool.
	static const QString StoragePath;

	explicit WebFetchTool(QObject* parent = nullptr);
	~WebFetchTool() override;

	QString name() const override;
	QString description() const override;
	QJsonObject parameters() const override;
	void execute(
		const QString& toolCallId,
		const QJsonObject& args,
		std::function<void(const QJsonObject& result)> done) override;
	void cancel() override;

	static QString extractTextFromHtml(const QString& html);
	static QString decodeEntities(const QString& text);

	private:
	struct Job {
		QNetworkReply* reply = nullptr;
		QTimer* timer = nullptr;
		QByteArray body;
		bool tooLarge = false;
		QString format;
		QString toolCallId;
		std::function<void(const QJsonObject& result)> done;
	};

	void completeJob(Job* job, QJsonObject result);
	// Writes the full output to StoragePath; returns the file path, or an
	// empty string when saving failed.
	QString saveToFile(const Job& job, const QString& content,
					   const QString& mime) const;

	QNetworkAccessManager m_manager;
	QList<Job*> m_jobs;
};

} // namespace ZShell::llm
