var LOCAL_DATASETS_KEY     = 'wmd_export_datasets';
var LOCAL_LAST_DATASET_KEY = 'wmd_export_last_dataset';
var LOCAL_LAST_DATASET_INDEX_KEY = 'dataset_select_last_index';

///////////////////////////////////////////////////////////////////////////////

var columnsMeta     = {};
var selectedColumns = [];
var datasets        = [];
var computedColumns = {}; // name -> expression (e.g. "!auto_renew")

var DRAGGED_ROW     = null;

///////////////////////////////////////////////////////////////////////////////
	
document.addEventListener("DOMContentLoaded", async function() {
	await initApp();
	showBody();
});

///////////////////////////////////////////////////////////////////////////////

async function initApp() {
	if (!IS_ADMIN) {
		var els = document.querySelectorAll('.hidden-if-not-admin');
		for (var i = 0; i < els.length; i++) {
			els[i].style.display = 'none';
		}
	}

	// Run once on page load
	function adjustMenuControl() {
	  const menu = document.getElementById('menucontrol');
	  if (window.innerWidth >= 768) {
		menu.style.width = '320px';
	  } else {
		menu.style.width = ''; // reset or leave default
	  }
	}

	// Initial check
	adjustMenuControl();
	// Also run whenever the window is resized
	window.addEventListener('resize', adjustMenuControl);

	
	var loggedIn = await checkAuthSession();
    if (!loggedIn) return;
	startAuthSessionMonitor();
	initEventButtons();
	
	applyViewModeRestrictions();

	loadCategories();
	loadColumns();
	await initDatasets();
	rebuildComputedListUI();
	setupEventHandlers();
	updateSummary();
}

///////////////////////////////////////////////////////////////////////////////

function setStatus(message, isError) {
	var area = document.getElementById('status-area');
	if (!area) return;
	area.textContent = message || '';
	area.className = 'status-area';
	if (message) {
		area.classList.add(isError ? 'status-error' : 'status-ok');
	}
}

///////////////////////////////////////////////////////////////////////////////

function setSummary(text) {
	var el = document.getElementById('export-summary');
	if (!el) return;
	el.textContent = text;
}

///////////////////////////////////////////////////////////////////////////////

function setPreview(html) {
	var area = document.getElementById('preview-area');
	if (!area) return;
	area.innerHTML = html || '';
}

///////////////////////////////////////////////////////////////////////////////

function loadCategories() {
	var url = API_BASE_URL + '?c=list&t=category&oper=user';

	fetch(url, { credentials: 'same-origin' })
		.then(function (res) { return res.json(); })
		.then(function (data) {
			var select = document.getElementById('filter_category');
			if (!select) return;

			if (!data || !Array.isArray(data.ids)) {
				return;
			}

			data.ids.forEach(function (cat) {
				var opt = document.createElement('option');
				opt.value = cat.id;
				opt.textContent = cat.name;
				select.appendChild(opt);
			});
		})
		.catch(function () {
			// ignore, "All categories" remains
		});
}

function makeDefaultLabelFromName(name) {
	var parts = String(name).split('_');
	for (var i = 0; i < parts.length; i++) {
		if (!parts[i]) continue;
		parts[i] = parts[i].charAt(0).toUpperCase() + parts[i].slice(1);
	}
	return parts.join(' ');
}

function loadColumns() {
	var url = API_BASE_URL + '?c=list&t=domain&oper=columns';

	fetch(url, { credentials: 'same-origin' })
		.then(function (res) { return res.json(); })
		.then(function (data) {
			var container = document.getElementById('columns-list');
			if (!container) return;

			container.innerHTML = '';

			if (!data || !data.columns) {
				container.textContent = 'Could not load columns from API.';
				return;
			}

			columnsMeta = data.columns;

			// In normal-user / admin-normal mode, columns are driven only by datasets.
			if (!IS_ADMIN) {
				container.textContent = 'Column configuration is managed by an administrator.';
				return;
			}

			// Load saved selection (local list of selected columns)
			var savedSelection = [];
			try {
				var stored = localStorage.getItem('wmd_add_domain_columns');
				if (stored) {
					savedSelection = JSON.parse(stored);
					if (!Array.isArray(savedSelection)) savedSelection = [];
				}
			} catch (e) {
				savedSelection = [];
			}

			// Ensure domain is always selected and always first.
			if (!savedSelection.includes("domain")) {
				savedSelection.unshift("domain");
			}

			var selectedNames = new Set(savedSelection);
			selectedColumns = savedSelection.slice();

			// Buckets:
			var selectedList = [];
			var customList   = [];
			var otherList    = [];

			// 1️⃣ FIRST: Add selected columns in exact saved order, with domain first
			selectedColumns.forEach(function (colName) {
				if (columnsMeta[colName]) {
					selectedList.push(colName);
				}
			});

			// 2️⃣ NEXT: Sort remaining columns into custom and other
			Object.keys(columnsMeta).forEach(function (colName) {
				var col = columnsMeta[colName];

				// Must appear in grid
				if (!col || !(col.gridview == 1 || col.gridview === true)) {
					return;
				}

				// Already in selected list
				if (selectedNames.has(colName)) return;

				// Custom field
				if (col.custom == 1 || col.custom == "1") {
					customList.push(colName);
				} else {
					otherList.push(colName);
				}
			});

			// Final ordering: domain → selected → custom → others
			var ordered = [];

			// Domain ALWAYS first
			if (selectedList.includes("domain")) {
				ordered.push("domain");
			}

			// Then selected columns except domain
			ordered = ordered.concat(selectedList.filter(c => c !== "domain"));

			// Then custom columns
			ordered = ordered.concat(customList);

			// Finally other normal columns
			ordered = ordered.concat(otherList);

			// Build DOM
			ordered.forEach(function (colName) {
				var col = columnsMeta[colName];
				var label = col.label || makeDefaultLabelFromName(colName);
				columnsMeta[colName].label = label;

				var item = document.createElement('div');
				item.className = 'columns-list-item';

				var checkbox = document.createElement('input');
				checkbox.type = 'checkbox';
				checkbox.value = colName;
				checkbox.checked = selectedNames.has(colName);
				checkbox.className = 'columns-list-checkbox';

				var textWrap = document.createElement('div');
				textWrap.className = 'columns-list-text';

				var labelMain = document.createElement('div');
				labelMain.className = 'columns-list-label-main';
				labelMain.textContent = label;

				var labelKey = document.createElement('div');
				labelKey.className = 'columns-list-label-key';
				labelKey.textContent = colName;

				textWrap.appendChild(labelMain);
				textWrap.appendChild(labelKey);

				item.appendChild(checkbox);
				item.appendChild(textWrap);

				container.appendChild(item);

				checkbox.addEventListener('change', onColumnSelectionChanged);
			});

			rebuildSelectedColumnsFromChecks();
			rebuildSelectedColumnsConfigUI();
			updateSummary();
		})
		.catch(function () {
			var container = document.getElementById('columns-list');
			if (container) {
				container.textContent = 'Error loading columns from API.';
			}
		});
}


function getCheckedColumns() {
	var container = document.getElementById('columns-list');
	if (!container) return [];
	var checkboxes = container.querySelectorAll('.columns-list-checkbox');
	var list       = [];
	for (var i = 0; i < checkboxes.length; i++) {
		if (checkboxes[i].checked) {
			list.push(checkboxes[i].value);
		}
	}

	// Preserve any computed columns that were already selected
	Object.keys(computedColumns).forEach(function (name) {
		if (selectedColumns.indexOf(name) !== -1 && list.indexOf(name) === -1) {
			list.push(name);
		}
	});

	return list;
}

function onColumnSelectionChanged() {
	if (!IS_ADMIN) {
		return;
	}
	rebuildSelectedColumnsFromChecks();
	rebuildSelectedColumnsConfigUI();
	updateSummary();
}

function rebuildSelectedColumnsFromChecks() {
	selectedColumns = getCheckedColumns();
}

function rebuildSelectedColumnsConfigUI() {
	var container = document.getElementById('selected-columns-config');
	if (!container) return;

	container.innerHTML = '';

	if (!selectedColumns.length) {
		container.textContent = 'No columns selected.';
		return;
	}

	var table = document.createElement('table');
	table.className = 'selected-columns-table';

	var thead = document.createElement('thead');
	var headerRow = document.createElement('tr');

	if(IS_ADMIN) {
		var thDrag = document.createElement('th');
		thDrag.textContent = '';
		headerRow.appendChild(thDrag);
	}

	var thInternal = document.createElement('th');
	thInternal.textContent = 'Internal name';
	headerRow.appendChild(thInternal);

	var thLabel = document.createElement('th');
	thLabel.textContent = 'CSV column heading';
	headerRow.appendChild(thLabel);

	thead.appendChild(headerRow);
	table.appendChild(thead);

	var tbody = document.createElement('tbody');

	selectedColumns.forEach(function (colName) {

		var meta  = columnsMeta[colName] || {};
		var label = meta.label || makeDefaultLabelFromName(colName);

		var row = document.createElement('tr');
		row.draggable = !!IS_ADMIN;
		row.dataset.col = colName;

		if(IS_ADMIN) {
			var handle = document.createElement("td");
			handle.innerHTML = '<span class="col-drag-handle">☰</span>';
			row.appendChild(handle);
		}

		if (IS_ADMIN) {
			row.addEventListener('dragstart', function () {
				DRAGGED_ROW = row;
				setTimeout(function () {
					row.classList.add('dragging');
				}, 0);
			});

			row.addEventListener('dragend', function () {
				DRAGGED_ROW = null;
				row.classList.remove('dragging');
			});

			row.addEventListener('dragover', function (e) {
				e.preventDefault();
				row.classList.add('drag-over');
			});

			row.addEventListener('dragleave', function () {
				row.classList.remove('drag-over');
			});

			row.addEventListener('drop', function (e) {
				e.preventDefault();
				row.classList.remove('drag-over');

				if (!DRAGGED_ROW || DRAGGED_ROW === row) return;

				var tb   = row.parentNode;
				var rows = Array.from(tb.querySelectorAll("tr"));

				var draggedIndex = rows.indexOf(DRAGGED_ROW);
				var targetIndex  = rows.indexOf(row);

				if (draggedIndex < targetIndex)
					row.after(DRAGGED_ROW);
				else
					row.before(DRAGGED_ROW);

				updateColumnOrderFromDOM();
			});
		} else {
			//handle.style.opacity = 0.4;
		}

		var tdName = document.createElement('td');
		tdName.textContent = colName;
		row.appendChild(tdName);

		var tdHeader = document.createElement('td');
		var input    = document.createElement('input');
		input.type        = 'text';
		input.className   = 'header-input';
		input.id          = 'header_for_' + colName;
		input.placeholder = label;
		if (!IS_ADMIN) {
			input.readOnly = true;
		}
		tdHeader.appendChild(input);
		row.appendChild(tdHeader);

		tbody.appendChild(row);
	});

	table.appendChild(tbody);
	container.appendChild(table);

	updateColumnOrderFromDOM();
}

function collectHeaderLabels() {
	var labels = {};
	selectedColumns.forEach(function (colName) {
		var input = document.getElementById('header_for_' + colName);
		var value = '';
		if (input && input.value.trim() !== '') {
			value = input.value.trim();
		} else {
			var meta  = columnsMeta[colName] || {};
			var label = meta.label || makeDefaultLabelFromName(colName);
			value     = label;
		}
		labels[colName] = value;
	});
	return labels;
}

function updateSummary() {
	var catSelect = document.getElementById('filter_category');
	var queryInput = document.getElementById('filter_query');

	var parts = [];

	if (catSelect) {
		var val  = catSelect.value;
		var text = catSelect.options[catSelect.selectedIndex]
			? catSelect.options[catSelect.selectedIndex].textContent
			: '';
		if (val === '') {
			parts.push('Category: all');
		} else {
			parts.push('Category: ' + text);
		}
	}

	if (queryInput && queryInput.value.trim() !== '') {
		parts.push('Query: ' + queryInput.value.trim());
	}

	if (selectedColumns.length) {
		var colSummary = selectedColumns.map(function (c) {
			return Object.prototype.hasOwnProperty.call(computedColumns, c)
				? c + ' (computed)'
				: c;
		});
		parts.push('Columns: ' + colSummary.join(', '));
	} else {
		parts.push('Columns: none selected');
	}

	var boolSel = document.getElementById('bool_format');
	if (boolSel) {
		var v    = boolSel.value;
		var desc = '1/0';
		if (v === 'YN') desc = 'Y/N';
		else if (v === 'YESNO') desc = 'Yes/No';
		else if (v === 'TF') desc = 'True/False';
		else if (v === 'EN') desc = 'Enabled/Disabled';
		parts.push('Booleans: ' + desc);
	}

	setSummary(parts.join(' | '));
}

function rebuildComputedListUI() {
	var container = document.getElementById('computed-list');
	if (!container) return;

	var names = Object.keys(computedColumns);
	if (!names.length) {
		container.textContent = 'None defined.';
		return;
	}

	container.innerHTML = '';
	names.forEach(function (name) {
		var row = document.createElement('div');
		row.className = 'computed-item';

		var span = document.createElement('span');
		span.className  = 'computed-name';
		span.textContent = name + ' = ' + computedColumns[name];

		var btn = document.createElement('button');
		btn.type      = 'button';
		btn.className = 'btn btn-danger btn-sm';
		btn.textContent = 'Delete';

		if (!IS_ADMIN) {
			btn.disabled = true;
		} else {
			btn.addEventListener('click', function () {
				delete computedColumns[name];
				selectedColumns = selectedColumns.filter(function (c) {
					return c !== name;
				});
				rebuildComputedListUI();
				rebuildSelectedColumnsConfigUI();
				updateSummary();
			});
		}

		row.appendChild(span);
		row.appendChild(btn);
		container.appendChild(row);
	});
}

function loadDatasetsFromLocalStorage() {
	var userDatasets = [];
	try {
		var stored = localStorage.getItem(LOCAL_DATASETS_KEY);
		if (stored) {
			userDatasets = JSON.parse(stored);
			if (!Array.isArray(userDatasets)) {
				userDatasets = [];
			}
		}
	} catch (e) {
		userDatasets = [];
	}
	datasets = userDatasets;
	populateDatasetSelect();

	try {
		var lastName = localStorage.getItem(LOCAL_LAST_DATASET_KEY);
		if (lastName) {
			var select = document.getElementById('dataset_select');
			if (select) {
				for (var i = 0; i < datasets.length; i++) {
					if (datasets[i].name === lastName) {
						select.value = String(i);
						break;
					}
				}
			}
		}
	} catch (e) {}
}

function populateDatasetSelect() {
	var select = document.getElementById('dataset_select');
	if (!select) return;

	select.innerHTML = '';
	var optDefault = document.createElement('option');
	optDefault.value = '';
	optDefault.textContent = 'No data set selected';
	select.appendChild(optDefault);

	datasets.forEach(function (ds, index) {
		var opt = document.createElement('option');
		opt.value = String(index);
		opt.textContent = ds.name;
		select.appendChild(opt);
	});
	
	setTimeout(handleLoadDataset, 500);
}

function saveDatasetsToLocalStorage() {
	if (!IS_ADMIN) return;
	try {
		localStorage.setItem(LOCAL_DATASETS_KEY, JSON.stringify(datasets));
	} catch (e) {}
}

async function loadDatasetsFromServer() {
	try {
		const raw = await get_config_data("export_domains_tool", API_BASE_URL);
		if (!raw) return [];

		const parsed = JSON.parse(raw);
		if (parsed && Array.isArray(parsed.datasets)) {
			return parsed.datasets;
		}
		return [];
	} catch (e) {
		console.warn("Failed to load config from server:", e);
		return [];
	}
}


async function initDatasets() {
	if (IS_ADMIN) {
		// Admin setup mode: Prefer server config, fallback to local storage
		const serverSets = await loadDatasetsFromServer();
		if (serverSets.length) {
			datasets = serverSets;
			saveDatasetsToLocalStorage();
			populateDatasetSelect();
		} else {
			// Fallback to local storage
			loadDatasetsFromLocalStorage();
		}
	} else {
		// Regular-user mode: Server-defined datasets ONLY
		datasets = await loadDatasetsFromServer();
		populateDatasetSelect();
	}
}


function handleSaveDataset() {
	if (!IS_ADMIN) {
		setStatus('Saving data sets is only available to administrators in setup mode.', true);
		return;
	}

	var nameInput = document.getElementById('dataset_name');
	if (!nameInput) return;

	var name = nameInput.value.trim();
	if (name === '') {
		setStatus('Please enter a name for the data set.', true);
		return;
	}

	if (!selectedColumns.length) {
		setStatus('Please select at least one column before saving a data set.', true);
		return;
	}

	var catSelect  = document.getElementById('filter_category');
	var queryInput = document.getElementById('filter_query');
	var labels     = collectHeaderLabels();
	var boolSel    = document.getElementById('bool_format');

	var dataset = {
		name: name,
		category: catSelect ? catSelect.value : '',
		query: queryInput ? queryInput.value.trim() : '',
		columns: selectedColumns.slice(),
		labels: labels,
		boolFormat: boolSel ? boolSel.value : '10',
		computed: Object.assign({}, computedColumns)
	};

	var replaced = false;
	for (var i = 0; i < datasets.length; i++) {
		if (datasets[i].name === name) {
			datasets[i] = dataset;
			replaced    = true;
			break;
		}
	}
	if (!replaced) {
		datasets.push(dataset);
	}

	saveDatasetsToLocalStorage();
	
	if (IS_ADMIN) {
		set_config_data("export_domains_tool", { datasets: datasets }, API_BASE_URL)
			.then(()=> setStatus('Data set "' + name + '" saved (server updated).', false))
			.catch(e=> setStatus('Saved locally, but server update failed: ' + e, true));
	}


	try {
		localStorage.setItem(LOCAL_LAST_DATASET_KEY, name);
	} catch (e) {}

	setStatus('Data set "' + name + '" saved.', false);
	populateDatasetSelect();
}

function applyDataset(ds) {
	var catSelect  = document.getElementById('filter_category');
	var queryInput = document.getElementById('filter_query');

	if (catSelect) {
		catSelect.value = ds.category || '';
	}
	if (queryInput) {
		queryInput.value = ds.query || '';
	}

	computedColumns = ds.computed ? Object.assign({}, ds.computed) : {};
	rebuildComputedListUI();

	var boolSel = document.getElementById('bool_format');
	if (boolSel && ds.boolFormat) {
		boolSel.value = ds.boolFormat;
	}

	if (!Array.isArray(ds.columns)) {
		ds.columns = [];
	}

	if (!IS_ADMIN) {
		// Non-admin: columns are taken as-is from dataset
		selectedColumns = ds.columns.slice();
		rebuildSelectedColumnsConfigUI();
	} else {
		var container = document.getElementById('columns-list');
		if (container) {
			var checkboxes = container.querySelectorAll('.columns-list-checkbox');
			for (var i = 0; i < checkboxes.length; i++) {
				var cb    = checkboxes[i];
				cb.checked = ds.columns.indexOf(cb.value) !== -1;
			}
		}
		selectedColumns = ds.columns.slice();
		rebuildSelectedColumnsConfigUI();
	}

	if (ds.labels) {
		Object.keys(ds.labels).forEach(function (colName) {
			var input = document.getElementById('header_for_' + colName);
			if (input) {
				input.value = ds.labels[colName];
			}
		});
	}

	updateSummary();
}

function handleLoadDataset() {
	var select = document.getElementById('dataset_select');
	if (!select) return;

	if (select.value === '') {
		var restoredIndex = -1;

		try {
			restoredIndex = parseInt(
				localStorage.getItem(LOCAL_LAST_DATASET_INDEX_KEY),
				10
			);
		} catch (e) {}

		if (
			restoredIndex >= 0 &&
			restoredIndex < select.options.length &&
			!select.options[restoredIndex].disabled &&
			select.options[restoredIndex].value !== ''
		) {
			select.selectedIndex = restoredIndex;
		} else {
			for (var i = 0; i < select.options.length; i++) {
				var opt = select.options[i];

				if (!opt.disabled && opt.value !== '') {
					select.selectedIndex = i;
					break;
				}
			}
		}
	}

	if (select.value === '') {
		setStatus('Please select a data set to load.', true);
		return;
	}

	var index = parseInt(select.value, 10);
	if (isNaN(index) || index < 0 || index >= datasets.length) {
		setStatus('Invalid data set selection.', true);
		return;
	}

	var ds = datasets[index];
	applyDataset(ds);

	var nameInput = document.getElementById('dataset_name');
	if (nameInput && IS_ADMIN) {
		nameInput.value = ds.name;
	}

	try {
		localStorage.setItem(
			LOCAL_LAST_DATASET_INDEX_KEY,
			String(select.selectedIndex)
		);
	} catch (e) {}

	if (IS_ADMIN) {
		try {
			localStorage.setItem(LOCAL_LAST_DATASET_KEY, ds.name);
		} catch (e) {}
	}

	setStatus('Data set "' + ds.name + '" loaded.', false);
}



function handleDeleteDataset() {
	if (!IS_ADMIN) {
		setStatus('Deleting data sets is only available to administrators in setup mode.', true);
		return;
	}

	var select = document.getElementById('dataset_select');
	if (!select) return;
	if (select.value === '') {
		setStatus('Please select a data set to delete.', true);
		return;
	}

	var index = parseInt(select.value, 10);
	if (isNaN(index) || index < 0 || index >= datasets.length) {
		setStatus('Invalid data set selection.', true);
		return;
	}

	var name = datasets[index].name;

	if (!window.confirm('Delete data set "' + name + '"?')) {
		return;
	}

	datasets.splice(index, 1);
	saveDatasetsToLocalStorage();
	
	set_config_data("export_domains_tool", { datasets: datasets }, API_BASE_URL)
	.then(()=> setStatus('Data set "' + name + '" deleted (server updated).', false))
	.catch(e=> setStatus('Deleted locally, but server update failed: ' + e, true));


	var nameInput = document.getElementById('dataset_name');
	if (nameInput && nameInput.value.trim() === name) {
		nameInput.value = '';
	}

	setStatus('Data set "' + name + '" deleted.', false);
	loadDatasetsFromLocalStorage();
}

function getCellValue(row, colName) {
	var val = '';
	if (row && Object.prototype.hasOwnProperty.call(row, colName)) {
		val = row[colName];
	} else if (row && row.cell && typeof row.cell === 'object') {
		if (Object.prototype.hasOwnProperty.call(row.cell, colName)) {
			val = row.cell[colName];
		}
	}
	if (val === null || typeof val === 'undefined') {
		val = '';
	}
	return val;
}

function mapBoolean(val, format) {
	var b = (val === 1 || val === '1' || val === true || val === 'true');

	switch (format) {
		case 'YN':
			return b ? 'Y' : 'N';
		case 'YESNO':
			return b ? 'Yes' : 'No';
		case 'TF':
			return b ? 'True' : 'False';
		case 'EN':
			return b ? 'Enabled' : 'Disabled';
		case '10':
		default:
			return b ? '1' : '0';
	}
}

function normalizeValue(val, boolFormat) {
	if (val === null || typeof val === 'undefined') {
		return '';
	}

	if (
		val === 1 || val === 0 ||
		val === '1' || val === '0' ||
		val === true || val === false
	) {
		var b = (val === 1 || val === '1' || val === true);
		return mapBoolean(b ? 1 : 0, boolFormat);
	}

	return val;
}

function evalComputedExpression(expr, row, boolFormat) {
	if (!expr) return '';
	expr = String(expr).trim();

	if (expr.charAt(0) === '!') {
		var base = expr.slice(1);
		if (!base) return '';
		var raw = getCellValue(row, base);
		var b   = (raw === 1 || raw === '1' || raw === true || raw === 'true');
		var val = b ? 0 : 1;
		return normalizeValue(val, boolFormat);
	}

	return '';
}

function extractRowValues(row, cols, boolFormat) {
	var values = [];
	for (var i = 0; i < cols.length; i++) {
		var colName = cols[i];

		if (Object.prototype.hasOwnProperty.call(computedColumns, colName)) {
			var exprVal = evalComputedExpression(computedColumns[colName], row, boolFormat);
			values.push(String(exprVal));
			continue;
		}

		var val = getCellValue(row, colName);
		val     = normalizeValue(val, boolFormat);
		values.push(String(val));
	}
	return values;
}

function updateColumnOrderFromDOM() {
	var tbody = document.querySelector('#selected-columns-config table tbody');
	if (!tbody) return;

	selectedColumns = Array.from(tbody.querySelectorAll('tr'))
		.map(function (tr) { return tr.dataset.col; });
}

function csvEscape(value) {
	var needsQuote = /[",\r\n]/.test(value);
	var v          = value.replace(/"/g, '""');
	return needsQuote ? '"' + v + '"' : v;
}

async function fetchGridPage(params) {
	var url = API_BASE_URL + '?' + params.toString();
	var res = await fetch(url, { credentials: 'same-origin' });
	var data = await res.json();
	return data;
}

function isComputedColumn(colName) {
    return Object.prototype.hasOwnProperty.call(computedColumns, colName);
}

async function runExport(isPreview) {
	setStatus('', false);
	setPreview('');

	if (!selectedColumns.length) {
		setStatus('Please select at least one column or load a data set before exporting.', true);
		return;
	}

	var rowsPerPageInput = document.getElementById('rows_per_page');
	var rowsPerPage      = 500;
	if (rowsPerPageInput && rowsPerPageInput.value) {
		var val = parseInt(rowsPerPageInput.value, 10);
		if (!isNaN(val) && val > 0) {
			rowsPerPage = val;
		}
	}

	var catSelect  = document.getElementById('filter_category');
	var queryInput = document.getElementById('filter_query');

	var categoryId = catSelect ? catSelect.value : '';
	var query      = queryInput ? queryInput.value.trim() : '';

	var headerLabels      = collectHeaderLabels();
	var boolSel           = document.getElementById('bool_format');
	var currentBoolFormat = boolSel ? boolSel.value : '10';

	try {
		setStatus(isPreview ? 'Fetching data for preview...' : 'Fetching data for export...', false);

		var page       = 1;
		var allRows    = [];
		var totalPages = null;

		while (true) {
			var params = new URLSearchParams();
			params.set('c', 'grid');
			params.set('t', 'domain');
			params.set('oper', 'get');
			var apiColumns = selectedColumns.filter(function (c) {
				return !isComputedColumn(c);
			});
			params.set('columns', apiColumns.join(','));
			params.set('page', String(page));
			params.set('rows', String(rowsPerPage));

			if (categoryId) {
				params.set('cid', categoryId);
			}
			if (query) {
				params.set('query', query);
			}

			var data = await fetchGridPage(params);

			if (!data || !Array.isArray(data.rows)) {
				setStatus('API did not return expected grid data.', true);
				return;
			}

			var rowsForThisPage = data.rows.map(function (row) {
				return extractRowValues(row, selectedColumns, currentBoolFormat);
			});

			if (isPreview) {
				allRows = allRows.concat(rowsForThisPage);
				if (allRows.length >= 20) {
					allRows = allRows.slice(0, 20);
					break;
				}
			} else {
				allRows = allRows.concat(rowsForThisPage);
			}

			if (totalPages === null) {
				var total    = data.total;
				var totalNum = parseInt(total, 10);
				if (isNaN(totalNum) || totalNum < 1) {
					totalNum = 1;
				}
				totalPages = totalNum;
			}

			if (page >= totalPages) {
				break;
			}

			page++;
			if (isPreview && allRows.length >= 20) {
				break;
			}
		}

		if (!allRows.length) {
			setStatus('No rows found for the current filters.', false);
			return;
		}

		if (isPreview) {
			var html = '<table class="preview-table"><thead><tr>';
			selectedColumns.forEach(function (colName) {
				var label = headerLabels[colName] || colName;
				html += '<th>' + String(label).replace(/</g, '&lt;').replace(/>/g, '&gt;') + '</th>';
			});
			html += '</tr></thead><tbody>';

			allRows.forEach(function (rowVals) {
				html += '<tr>';
				rowVals.forEach(function (val) {
					var safe = String(val).replace(/</g, '&lt;').replace(/>/g, '&gt;');
					html += '<td>' + safe + '</td>';
				});
				html += '</tr>';
			});

			html += '</tbody></table>';
			setPreview(html);
			setStatus('Preview shows the first ' + allRows.length + ' rows.', false);
			return;
		}

		var lines = [];

		var headerLineValues = [];
		selectedColumns.forEach(function (colName) {
			headerLineValues.push(csvEscape(headerLabels[colName] || colName));
		});
		lines.push(headerLineValues.join(','));

		allRows.forEach(function (rowVals) {
			var csvVals = rowVals.map(function (v) {
				return csvEscape(String(v));
			});
			lines.push(csvVals.join(','));
		});

		var csvContent = lines.join('\r\n');
		var blob       = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });

		var now  = new Date();
		var y    = String(now.getFullYear());
		var m    = String(now.getMonth() + 1).padStart(2, '0');
		var d    = String(now.getDate()).padStart(2, '0');
		var filename = 'wmd-domains-export-' + y + m + d + '.csv';

		var link = document.createElement('a');
		if (link.download !== undefined) {
			var url = URL.createObjectURL(blob);
			link.setAttribute('href', url);
			link.setAttribute('download', filename);
			link.style.visibility = 'hidden';
			document.body.appendChild(link);
			link.click();
			document.body.removeChild(link);
			URL.revokeObjectURL(url);
			setStatus('Export completed. CSV downloaded.', false);
		} else {
			setStatus('This browser does not support automatic CSV download.', true);
		}
	} catch (e) {
		setStatus('Error during export: ' + e, true);
	}
}

function handleAddComputed() {
	if (!IS_ADMIN) {
		setStatus('Computed columns can only be added by administrators in setup mode.', true);
		return;
	}

	var nameInput = document.getElementById('computed_col_name');
	var exprInput = document.getElementById('computed_col_expr');
	if (!nameInput || !exprInput) return;

	var name = nameInput.value.trim();
	var expr = exprInput.value.trim();

	if (!name.match(/^[a-zA-Z0-9_]+$/)) {
		setStatus('Invalid computed column name. Use only letters, numbers and underscores.', true);
		return;
	}
	if (!expr.startsWith('!')) {
		setStatus('Only !field expressions are supported at this time.', true);
		return;
	}
	if (columnsMeta[name]) {
		setStatus('A real column already uses this name.', true);
		return;
	}

	computedColumns[name] = expr;

	if (selectedColumns.indexOf(name) === -1) {
		selectedColumns.push(name);
	}

	rebuildComputedListUI();
	rebuildSelectedColumnsConfigUI();
	updateSummary();

	nameInput.value = '';
	exprInput.value = '';
	setStatus('Computed column "' + name + '" added.', false);
}

function setupEventHandlers() {
	var btnSave = document.getElementById('btn_save_dataset');
	if (btnSave && IS_ADMIN) {
		btnSave.addEventListener('click', handleSaveDataset);
	}

	var btnLoad = document.getElementById('btn_load_dataset');
	if (btnLoad) {
		btnLoad.addEventListener('click', handleLoadDataset);
	}

	var btnDelete = document.getElementById('btn_delete_dataset');
	if (btnDelete && IS_ADMIN) {
		btnDelete.addEventListener('click', handleDeleteDataset);
	}

	var catSelect = document.getElementById('filter_category');
	if (catSelect) {
		catSelect.addEventListener('change', updateSummary);
	}

	var queryInput = document.getElementById('filter_query');
	if (queryInput) {
		queryInput.addEventListener('change', updateSummary);
		queryInput.addEventListener('keyup', function () {
			updateSummary();
		});
	}

	var btnPreview = document.getElementById('btn_preview');
	if (btnPreview) {
		btnPreview.addEventListener('click', function () {
			runExport(true);
		});
	}

	var btnExport = document.getElementById('btn_export');
	if (btnExport) {
		btnExport.addEventListener('click', function () {
			runExport(false);
		});
	}

	var btnAddComputed = document.getElementById('btn_add_computed');
	if (btnAddComputed && IS_ADMIN) {
		btnAddComputed.addEventListener('click', handleAddComputed);
	}

	var boolSel = document.getElementById('bool_format');
	if (boolSel) {
		boolSel.addEventListener('change', function () {
			if (!IS_ADMIN) {
				updateSummary();
				return;
			}

			var dsSelect = document.getElementById('dataset_select');
			if (!dsSelect || dsSelect.value === '') {
				updateSummary();
				return;
			}

			var idx = parseInt(dsSelect.value, 10);
			if (isNaN(idx) || idx < 0 || idx >= datasets.length) {
				updateSummary();
				return;
			}
			var ds = datasets[idx];
			ds.boolFormat = boolSel.value;
			saveDatasetsToLocalStorage();
			setStatus('Boolean format saved for data set "' + ds.name + '".', false);
			updateSummary();
		});
	}

	var btnExportConfig = document.getElementById('btn_export_config');
	if (btnExportConfig && IS_ADMIN) {
		btnExportConfig.addEventListener('click', async function () {
			if (!datasets.length) {
				setStatus('No data sets available to save.', true);
				return;
			}

			setStatus('Saving configuration…', false);

			const config = { datasets: datasets };

			try {
				const ok = await set_config_data("export_domains_tool", config, API_BASE_URL);
				
				if (ok) {
					setStatus('Configuration saved to server successfully.', false);
				} else {
					setStatus('Failed to save configuration to server.', true);
				}

			} catch (err) {
				setStatus('Error saving configuration: ' + err.message, true);
			}
		});

	}
}

function applyViewModeRestrictions() {
	if (!IS_ADMIN) {
		// Hide all administrative configuration sections
		var adminSections = document.querySelectorAll('.data-set-config');
		adminSections.forEach(function (el) {
			el.style.display = 'none';
		});

		// Hide delete button in dataset row
		var deleteBtn = document.getElementById('btn_delete_dataset');
		if (deleteBtn) {
			deleteBtn.style.display = 'none';
		}
	}
}
