/**
 * @package    Joomla.Component.Builder
 *
 * @created    30th April, 2015
 * @author     Llewellyn van der Merwe <https://dev.vdm.io>
 * @git        Joomla Component Builder <https://git.vdm.dev/joomla/Component-Builder>
 * @copyright  Copyright (C) 2015 Vast Development Method. All rights reserved.
 * @license    GNU General Public License version 2 or later; see LICENSE.txt
 */

/* JS Document */

const memoryinitialization = [];

function setSessionMemory(key, values, merge = true) {
	if (merge) {
		values = mergeSessionMemory(key, values);
	} else {
		values = JSON.stringify(values);
	}

	if (typeof Storage !== "undefined") {
		sessionStorage.setItem(key, values);
	} else {
		memoryinitialization[key] = values;
	}
}

function mergeSessionMemory(key, values) {
	const oldValues = getSessionMemory(key);

	if (oldValues) {
		values = { ...oldValues, ...values };
	}

	return JSON.stringify(values);
}

function getSessionMemory(key, defaultValue = null) {
	if (typeof Storage !== "undefined") {
		const localValue = sessionStorage.getItem(key);

		if (isJsonString(localValue)) {
			defaultValue = JSON.parse(localValue);
		}
	} else if (typeof memoryinitialization[key] !== "undefined") {
		const localValue = memoryinitialization[key];

		if (isJsonString(localValue)) {
			defaultValue = JSON.parse(localValue);
		}
	}

	return defaultValue;
}

function isJsonString(str) {
	try {
		JSON.parse(str);
	} catch (e) {
		return false;
	}

	return true;
}

function getArrayFormat(items) {
	// Check if items is an object and not an array
	if (typeof items === 'object' && !Array.isArray(items)) {
		return Object.values(items);
	}
	return items;
}
class InitializationManager {
	#repoArea = document.getElementById('select-repo-area');
	#powersArea = document.getElementById('select-powers-area');
	#initButton = document.getElementById('init-selected-powers');
	#backButton = document.getElementById('back-to-select-repo');
	#loadingDiv = window.loadingDiv || null;
	#buildTable = typeof buildPowerSelectionTable === 'function' ? buildPowerSelectionTable : null;
	#drawTable = typeof drawPowerSelectionTable === 'function' ? drawPowerSelectionTable : null;

	currentRepo = null;
	currentArea = null;

	constructor() {
		this._bindRepoButtons();
		this._bindInitSelectedPowers();
		this._updateInitButtonState();
	}

	/** Getter for selected items using global window reference. */
	get selectedItems() {
		if (!Array.isArray(window.selectedPowerItems)) {
			window.selectedPowerItems = [];
		}
		return window.selectedPowerItems;
	}

	/** Setter for selected items with sync to window and button state update. */
	set selectedItems(items) {
		window.selectedPowerItems = items;
		this._updateInitButtonState();
	}

	/** Add items to selection if not already selected. */
	addSelectedItems(data) {
		if (!data || typeof data.length !== 'number') return;

		const updated = [...this.selectedItems];

		for (let i = 0; i < data.length; i++) {
			const item = data[i];
			if (!updated.some(existing => this.#isSameItem(existing, item))) {
				updated.push(item);
			}
		}

		this.selectedItems = updated;
	}

	/** Remove items from selection based on identity comparison. */
	removeSelectedItems(data) {
		if (!data || typeof data.length !== 'number') return;

		const updated = this.selectedItems.filter(existing => {
			for (let i = 0; i < data.length; i++) {
				if (this.#isSameItem(existing, data[i])) {
					return false;
				}
			}
			return true;
		});

		this.selectedItems = updated;
	}

	/** Check if two items are the same using GUID. */
	#isSameItem(a, b) {
		return a?.guid && b?.guid && a.guid === b.guid;
	}

	/** Enable/disable the init button based on selection state. */
	_updateInitButtonState() {
		if (this.#initButton) {
			this.#initButton.disabled = this.selectedItems.length === 0;
		}
	}

	_bindRepoButtons() {
		document.querySelectorAll('.select-repo-to-initialize').forEach(button => {
			button.addEventListener('click', (e) => this._handleRepoClick(e));
		});
	}

	_bindInitSelectedPowers() {
		if (this.#initButton) {
			this.#initButton.addEventListener('click', () => this._handleInitSelectedPowers());
		}
		if (this.#backButton) {
			this.#backButton.addEventListener('click', () => this._handleBackToRepos());
		}
	}

	_getInitFunctionName(area) {
		const powers = [
			'Joomla.Fieldtype',
			'Joomla.Power',
			'Repository',
			'Power'
		];

		return powers.includes(area) ? 'initSelectedPowers' : 'initSelectedPackages';
	}

	async _handleRepoClick(event) {
		const button = event.currentTarget;
		const repo = button?.dataset?.repo;
		const area = button?.dataset?.area;

		if (!repo || !area) {
			this._notify(Joomla.Text._("COM_COMPONENTBUILDER_MISSING_REPOSITORY_OR_AREA_DATA"), "danger");
			return;
		}

		this._showLoading();
		clearPowerSelectionTable();

		const url = `${UrlAjax}getRepoIndex&repo=${encodeURIComponent(repo)}&area=${encodeURIComponent(area)}`;

		try {
			const response = await fetch(url);

			if (!response.ok) throw new Error(`HTTP ${response.status}`);

			const data = await response.json();

			if (data.success && data.index && this.#buildTable) {
				const repoData = data.index[0];
				const {
					path = 'joomla/super-powers',
					read_branch = 'master',
					target,
					base = 'https://git.vdm.dev'
				} = repoData;

				const repo_base = (target === 'github') ? 'https://github.com' : base;
				const repo_path = (target === 'github') ? 'tree' : 'src/branch';

				window.targetPowerRepoUrl = `${repo_base}/${path}/${repo_path}/${read_branch}/`;

				this.#buildTable(repoData.index);

				setTimeout(() => {
					this._transitionTo(this.#repoArea, this.#powersArea);
					this._hideLoading();
				}, 500);

				this.currentRepo = repoData.guid;
				this.currentArea = area;
			} else {
				this._notify(data.message || Joomla.Text._("COM_COMPONENTBUILDER_FAILED_TO_RETRIEVE_REPOSITORY_INDEX"), "danger");
				this._hideLoading();
			}
		} catch (error) {
			console.error("Fetch error:", error);
			this._hideLoading();
			this._notify(Joomla.Text._("COM_COMPONENTBUILDER_NETWORK_OR_SERVER_ERROR_OCCURRED_WHILE_FETCHING_INDEX"), "danger");
		}
	}

	_handleBackToRepos() {
		this._transitionTo(this.#powersArea, this.#repoArea);
	}

	async _handleInitSelectedPowers() {
		if (!Array.isArray(this.selectedItems) || this.selectedItems.length === 0) {
			this._notify(Joomla.Text._("COM_COMPONENTBUILDER_NO_ITEMS_SELECTED"), "warning");
			return;
		}

		this._showLoading();

		const area = this.currentArea || 'error';
		const repo = this.currentRepo || 'error';

		const func = this._getInitFunctionName(area);

		try {
			// Convert selected items to form data
			const formData = new FormData();

			// Assuming Joomla expects `selected[]` for multiple values
			for (const item of this.selectedItems) {
				formData.append('selected[]', item.guid); // Only sending GUIDs
			}
			formData.append('area', area);
			formData.append('repo', repo);

			const response = await fetch(`${UrlAjax}${func}`, {
				method: 'POST',
				body: formData
			});

			if (!response.ok) throw new Error(`HTTP ${response.status}`);

			const data = await response.json();

			if (!data.success) {
				this._notify(data.message || Joomla.Text._("COM_COMPONENTBUILDER_FAILED_TO_INITIALIZE_SELECTED_POWERS"), "danger");
			} else {
				this._handleResultLog(data.result_log || {});
			}

			this._hideLoading();
			this._transitionTo(this.#powersArea, this.#repoArea);
		} catch (error) {
			console.error("Submission error:", error);
			this._notify(Joomla.Text._("COM_COMPONENTBUILDER_ERROR_OCCURRED_WHILE_INITIALIZING_POWERS"), "danger");

			this._hideLoading();
			this._transitionTo(this.#powersArea, this.#repoArea);
		}
	}

	_handleResultLog(resultLog) {
		const localGuids = this._normalizeGuids(resultLog.local);
		const notFoundGuids = this._normalizeGuids(resultLog.not_found);
		const addedGuids = this._normalizeGuids(resultLog.added);

		if (localGuids.length > 0) {
			this._notify(
				this._generateResultMessage(localGuids, 'local'),
				'info'
			);
		}

		if (notFoundGuids.length > 0) {
			this._notify(
				this._generateResultMessage(notFoundGuids, 'not_found'),
				'info'
			);
		}

		if (addedGuids.length > 0) {
			this._notify(
				this._generateResultMessage(addedGuids, 'added'),
				'success'
			);
		}
	}

	_normalizeGuids(value) {
		if (!value) return [];

		if (Array.isArray(value)) {
			return value;
		}

		if (typeof value === 'object') {
			return Object.keys(value);
		}

		return [];
	}

	_generateResultMessage(guids, type) {
		const messages = {
			local: Joomla.Text._('COM_COMPONENTBUILDER_THESE_ITEMS_WERE_ALREADY_PRESENT_LOCALLY_AND_WERE_NOT_INITIALIZED'),
			not_found: Joomla.Text._('COM_COMPONENTBUILDER_THESE_ITEMS_COULD_NOT_BE_FOUND_IN_THE_REMOTE_REPOSITORY_AND_WERE_NOT_INITIALIZED'),
			added: Joomla.Text._('COM_COMPONENTBUILDER_THESE_ITEMS_WERE_SUCCESSFULLY_INITIALIZED')
		};

		const names = [];

		for (const guid of guids) {
			const item = this.selectedItems.find(i => i.guid === guid);
			if (item?.name) {
				names.push(item.name);
			}
		}

		if (names.length === 0) {
			return null;
		}

		return `${messages[type]}\n<br>- ${names.join('\n<br>- ')}`;
	}

	_transitionTo(hideEl, showEl) {
		if (hideEl && showEl) {
			UIkit.util.ready(() => {
				UIkit.util.removeClass(hideEl, 'uk-animation-slide-top-small');
				UIkit.util.removeClass(showEl, 'uk-animation-slide-bottom-small');
				UIkit.util.addClass(hideEl, 'uk-animation-slide-top-small');

				setTimeout(() => {
					hideEl.style.display = 'none';
					showEl.style.display = '';
					UIkit.util.addClass(showEl, 'uk-animation-slide-bottom-small');
					if (this.#drawTable) this.#drawTable();
				}, 300);
			});
		}
	}

	_showLoading() {
		if (this.#loadingDiv) this.#loadingDiv.style.display = 'block';
	}

	_hideLoading() {
		if (this.#loadingDiv) this.#loadingDiv.style.display = 'none';
	}

	_notify(message, type = 'info') {
		const alertTypes = {
			primary: 'alert-primary',
			info: 'alert-info',
			success: 'alert-success',
			warning: 'alert-warning',
			danger: 'alert-danger',
		};

		const alertClass = alertTypes[type] || alertTypes.primary;

		let container = document.getElementById('alert-container');
		if (!container) {
			container = document.createElement('div');
			container.id = 'alert-container';
			container.className = 'position-fixed top-0 start-50 translate-middle-x p-3';
			container.style.zIndex = '1060';
			document.body.appendChild(container);
		}

		const alert = document.createElement('div');
		alert.className = `alert ${alertClass} alert-dismissible fade show`;
		alert.setAttribute('role', 'alert');
		alert.innerHTML = `
			${message}
			<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
		`;

		container.appendChild(alert);

		setTimeout(() => {
			alert.classList.remove('show');
			alert.classList.add('hide');
			alert.addEventListener('transitionend', () => {
				alert.remove();
			});
		}, 5000);
	}
}