#include "scripteditordialog.h"
#include "../actors/scriptactor.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QLabel>
#include <QMessageBox>
#include <QFile>
#include <QTextStream>
#include <QDebug>

ScriptEditorDialog::ScriptEditorDialog(ScriptActor* actor, QWidget* parent)
	: QDialog(parent)
	, scriptActor_(actor)
	, highlighter_(nullptr)
{
	setWindowTitle("Edit Python Script");
	resize(800, 600);

	QVBoxLayout* mainLayout = new QVBoxLayout(this);

	// Info label
	QLabel* infoLabel = new QLabel("Available: items dict (item names -> values), sensors dict (sensor names -> values)\nReturn an integer to set the item value.", this);
	mainLayout->addWidget(infoLabel);

	// Create code editor - QCodeEditor already sets defaultStyle() in constructor
	editor_ = new QCodeEditor(this);
	editor_->setAutoIndentation(true);
	editor_->setAutoParentheses(true);
	editor_->setTabReplace(true);
	editor_->setTabReplaceSize(4);

	// Set up Python syntax highlighting using setHighlighter (handles style setup)
	highlighter_ = new QPythonHighlighter(nullptr);
	editor_->setHighlighter(highlighter_);

	mainLayout->addWidget(editor_);

	// Buttons
	QHBoxLayout* buttonLayout = new QHBoxLayout();
	QPushButton* runNowButton = new QPushButton("Run Now", this);
	QPushButton* saveButton = new QPushButton("Save", this);
	QPushButton* cancelButton = new QPushButton("Cancel", this);
	buttonLayout->addWidget(runNowButton);
	buttonLayout->addStretch();
	buttonLayout->addWidget(saveButton);
	buttonLayout->addWidget(cancelButton);
	mainLayout->addLayout(buttonLayout);

	// Connect signals
	connect(runNowButton, &QPushButton::clicked, this, &ScriptEditorDialog::runNow);
	connect(saveButton, &QPushButton::clicked, this, &ScriptEditorDialog::saveAndClose);
	connect(cancelButton, &QPushButton::clicked, this, &QDialog::reject);
	connect(editor_, &QCodeEditor::textChanged, this, &ScriptEditorDialog::onTextChanged);

	// Load current script
	loadScript();
}

ScriptEditorDialog::~ScriptEditorDialog()
{
}

void ScriptEditorDialog::loadScript()
{
	if(scriptActor_)
	{
		originalCode_ = scriptActor_->getScriptCode();
		if(originalCode_.isEmpty())
		{
			originalCode_ = getExampleScript();
		}
		editor_->setPlainText(originalCode_);
	}
}

QString ScriptEditorDialog::getExampleScript()
{
	return R"(# Example Python Script for ScriptActor
# This script runs when watched sensors change state
#
# Available variables:
#   items  - dict of item names to their current integer values
#   sensors - dict of sensor names to their current values
#   trigger_source - dict with info about what triggered this script:
#       type: "sensor", "item", or "manual"
#       name: name of the trigger
#       value: current value of the trigger
#   controlled_item - dict with info about the item this actor controls:
#       name, value, id
#
# Return value:
#   Return an integer to set the item state this actor is attached to
#   Return None or omit return to leave the item unchanged

# Print all available data for debugging
print("Items:", items)
print("Sensors:", sensors)
print("Trigger source:", trigger_source)
print("Controlled item:", controlled_item)

# Return 42 as a simple test
return 42

# --- More Examples Below ---

# Example 1: Simple threshold-based control
# Turn on item if any watched sensor exceeds threshold
# for sensor_name, value in sensors.items():
#     if value > 50:
#         return 1  # Turn on
# return 0  # Turn off

# Example 2: Combine multiple sensor values
# Calculate average of all watched sensors
# if sensors:
#     avg = sum(sensors.values()) / len(sensors)
#     return int(avg)

# Example 3: React to item state changes
# Check if a specific item has a certain value
# if items.get("some_item_name") == 1:
#     return 100
# return 0
)";
}

void ScriptEditorDialog::saveScript()
{
	if(!scriptActor_)
		return;

	QString newCode = editor_->toPlainText();
	scriptActor_->setScriptCode(newCode);

	// Trigger item update to sync to primary instance
	scriptActor_->triggerSync();
}

void ScriptEditorDialog::saveAndClose()
{
	if(!scriptActor_)
	{
		accept();
		return;
	}

	QString newCode = editor_->toPlainText();
	if(newCode != originalCode_)
	{
		// Basic Python syntax check - look for common issues
		int parenCount = 0;
		int bracketCount = 0;
		int braceCount = 0;
		for(const QChar& c : newCode)
		{
			if(c == '(') parenCount++;
			else if(c == ')') parenCount--;
			else if(c == '[') bracketCount++;
			else if(c == ']') bracketCount--;
			else if(c == '{') braceCount++;
			else if(c == '}') braceCount--;
		}

		if(parenCount != 0 || bracketCount != 0 || braceCount != 0)
		{
			QMessageBox::StandardButton reply = QMessageBox::question(
				this,
				"Unbalanced Brackets",
				"The script has unbalanced parentheses, brackets, or braces. Save anyway?",
				QMessageBox::Yes | QMessageBox::No
			);
			if(reply == QMessageBox::No)
				return;
		}

		saveScript();
	}

	accept();
}

void ScriptEditorDialog::onTextChanged()
{
	// Could add auto-save or other features here
}

void ScriptEditorDialog::runNow()
{
	if(!scriptActor_)
		return;

	// Temporarily set the script code from editor
	QString currentCode = editor_->toPlainText();
	QString savedCode = scriptActor_->getScriptCode();
	scriptActor_->setScriptCode(currentCode);

	// Run the script
	QVariant result = scriptActor_->runScriptNow();

	// Restore original script code
	scriptActor_->setScriptCode(savedCode);

	// Show result
	QString resultStr;
	if(result.isValid())
		resultStr = QString("Script returned: %1").arg(result.toString());
	else
		resultStr = "Script returned: None (no value)";

	QMessageBox::information(this, "Script Result", resultStr);
}