/**
 * file-upload-filepond.js
 *
 * Thin FilePond wrapper — replaces the old custom file-upload-queue.js.
 *
 * Architecture:
 *   1. Each <input type="file" class="tfe-file-picker"> is upgraded to a FilePond instance.
 *   2. FilePond handles drag-to-reorder, thumbnails, remove, validation — zero custom DOM.
 *   3. storeAsFile: true preserves native multipart form submission.
 *      Server receives files via $_FILES indexed by each input's name attribute
 *      (e.g. queue_file[tfe][], queue_file[video][], etc.).
 *   4. Type + size validation: via native FilePond options + FileValidateType/Size plugins.
 *      beforeAddFile is used ONLY for hybrid validation (e.g. per-type size limits)
 *      and returns true/false per the FilePond API contract.
 *   5. Order serialization: hidden inputs track file order from pond.getFiles().
 *   6. HTMX cleanup: generic destroyFilePondsIn(target) for all swaps, not just known IDs.
 */

(function () {
	"use strict";

	// ── Per-queue-type configuration ────────────────────────────────────
	// Single source of truth for validation. These specificatons are also
	// reflected in the PHP-synthesised accept attributes on inputs.

	var QUEUE_CONFIG = {
		tfe: {
			acceptedFileTypes: [
				"image/jpeg", "image/png", "image/gif", "image/webp",
				"application/pdf",
				"video/mp4", "video/webm", "video/ogg", "video/quicktime",
				"audio/mpeg", "audio/ogg", "audio/flac", "audio/x-wav", "audio/aac", "audio/mp4",
				"text/vtt",
				"application/zip", "application/x-tar", "application/gzip"
			],
			labelFileTypeNotAllowed: "Format non accepté",
			fileValidateTypeLabelExpectedTypes: "PDF, Images, Vidéos, Audio, VTT, Archives",
			maxFileSize: "500MB",
			labelMaxFileSizeExceeded: "Fichier trop volumineux",
			labelMaxFileSize: "Taille max: {filesize}",
			allowMultiple: true,
			// Per-extension size limits: certain types get higher caps.
			perExtensionMaxSize: {
				pdf: "100MB",
				mp4: "2GB", webm: "2GB", ogv: "2GB", mov: "2GB",
				mp3: "2GB", ogg: "2GB", oga: "2GB", wav: "2GB", flac: "2GB", aac: "2GB", m4a: "2GB"
			}
		},
		video: {
			acceptedFileTypes: ["video/mp4", "video/webm", "video/ogg", "video/quicktime"],
			labelFileTypeNotAllowed: "Format non accepté",
			fileValidateTypeLabelExpectedTypes: "MP4, WebM, OGV, MOV",
			maxFileSize: "500MB",
			labelMaxFileSizeExceeded: "Fichier trop volumineux",
			labelMaxFileSize: "Taille max: {filesize}",
			allowMultiple: true
		},
		audio: {
			acceptedFileTypes: ["audio/mpeg", "audio/ogg", "audio/flac", "audio/x-wav", "audio/aac", "audio/mp4"],
			labelFileTypeNotAllowed: "Format non accepté",
			fileValidateTypeLabelExpectedTypes: "MP3, OGG, FLAC, WAV, AAC, M4A",
			maxFileSize: "500MB",
			labelMaxFileSizeExceeded: "Fichier trop volumineux",
			labelMaxFileSize: "Taille max: {filesize}",
			allowMultiple: true
		},
		annexe: {
			acceptedFileTypes: ["application/pdf", "application/zip", "application/x-tar", "application/gzip"],
			labelFileTypeNotAllowed: "Format non accepté",
			fileValidateTypeLabelExpectedTypes: "PDF, ZIP, TAR, GZ",
			maxFileSize: "500MB",
			labelMaxFileSizeExceeded: "Fichier trop volumineux",
			labelMaxFileSize: "Taille max: {filesize}",
			allowMultiple: true
		},
		cover: {
			acceptedFileTypes: ["image/jpeg", "image/png", "image/webp"],
			labelFileTypeNotAllowed: "Seulement JPG, PNG ou WEBP",
			fileValidateTypeLabelExpectedTypes: "JPG, PNG, WEBP",
			maxFileSize: "20MB",
			labelMaxFileSizeExceeded: "Fichier trop volumineux",
			labelMaxFileSize: "Taille max: {filesize}",
			allowMultiple: false
		},
		note_intention: {
			acceptedFileTypes: ["application/pdf"],
			labelFileTypeNotAllowed: "Seulement PDF",
			fileValidateTypeLabelExpectedTypes: "PDF",
			maxFileSize: "100MB",
			labelMaxFileSizeExceeded: "Fichier trop volumineux",
			labelMaxFileSize: "Taille max: {filesize}",
			allowMultiple: false
		},
	};

	// Map input id → queue type
	var INPUT_ID_TO_TYPE = {
		"tfe-files-input":    "tfe",
		"tfe-files-input-2":  "tfe",
		"video-files-input":  "video",
		"audio-files-input":  "audio",
		"annexe-files-input": "annexe",
		"couverture":         "cover",
		"note_intention":     "note_intention",
	};

	// ── Helpers ───────────────────────────────────────────────────────────

	/**
	 * Parse a size string like "500MB" or "2GB" to bytes.
	 */
	function parseSize(str) {
		var m = str.match(/^(\d+(?:\.\d+)?)\s*(B|KB|MB|GB|TB)$/i);
		if (!m) return 0;
		var val = parseFloat(m[1]);
		var unit = m[2].toUpperCase();
		var mult = {B: 1, KB: 1024, MB: 1024*1024, GB: 1024*1024*1024, TB: 1024*1024*1024*1024};
		return Math.round(val * (mult[unit] || 1));
	}

	/**
	 * Get extension from filename (lowercase).
	 */
	function getExt(name) {
		var m = name.match(/\.([^./]+)$/);
		return m ? m[1].toLowerCase() : "";
	}

	// ── Order serialization ───────────────────────────────────────────────

	/**
	 * Create/update a hidden input that serializes the file order for a queue.
	 * Name: queue_order[<queueType>]
	 * Value: pipe-separated list of file names.
	 */
	function syncOrderInput(queueType, pond) {
		var form = pond.element ? pond.element.closest("form") : null;
		if (!form) return;

		var orderInput = form.querySelector("input[name='queue_order[" + queueType + "]']");
		var files = pond.getFiles();
		if (files.length === 0) {
			if (orderInput) orderInput.remove();
			return;
		}

		var names = [];
		for (var i = 0; i < files.length; i++) {
			names.push(files[i].filename || files[i].file.name);
		}

		if (!orderInput) {
			orderInput = document.createElement("input");
			orderInput.type = "hidden";
			orderInput.name = "queue_order[" + queueType + "]";
			form.appendChild(orderInput);
		}
		orderInput.value = names.join("|");
	}

	// ── FilePond configuration per queue type ─────────────────────────────

	function buildFilePondOptions(queueType, input) {
		var cfg = QUEUE_CONFIG[queueType];
		if (!cfg) return null;

		// Per-type max size overrides (for TFE: PDF=100MB, video/audio=2GB)
		var perExtMax = cfg.perExtensionMaxSize || {};

		return {
			allowMultiple: cfg.allowMultiple,
			allowReorder: true,
			allowProcess: false,
			storeAsFile: true,

			// ── Native FilePond validation ──
			acceptedFileTypes: cfg.acceptedFileTypes,
			labelFileTypeNotAllowed: cfg.labelFileTypeNotAllowed,
			fileValidateTypeLabelExpectedTypes: cfg.fileValidateTypeLabelExpectedTypes,
			maxFileSize: cfg.maxFileSize,
			labelMaxFileSizeExceeded: cfg.labelMaxFileSizeExceeded,
			labelMaxFileSize: cfg.labelMaxFileSize,

			// ── French labels ──
			labelIdle: "Glissez-déposez vos fichiers ou <span class='filepond--label-action'>Parcourir</span>",
			labelFileProcessing: "Chargement en cours",
			labelFileProcessingComplete: "Chargement terminé",
			labelFileProcessingAborted: "Chargement annulé",
			labelFileProcessingError: "Erreur lors du chargement",
			labelTapToCancel: "Appuyez pour annuler",
			labelTapToRetry: "Appuyez pour réessayer",
			labelTapToUndo: "Appuyez pour annuler",
			labelButtonRemoveItem: "Supprimer",
			labelButtonAbortItemLoad: "Annuler",
			labelButtonRetryItemLoad: "Réessayer",
			labelButtonProcessItem: "Charger",

			// ── Per-extension size validation (hybrid: FilePond validates global maxFileSize,
			//     beforeAddFile enforces per-extension limits via false return) ──
			beforeAddFile: function (item) {
				var f = item.file;
				var ext = getExt(f.name);
				if (ext && perExtMax[ext]) {
					var limit = parseSize(perExtMax[ext]);
					if (limit > 0 && f.size > limit) {
						// Return false per FilePond API contract — the FileValidateSize
						// plugin sets the error state via maxFileSize, but per-extension
						// cap violations must be rejected here.
						return false;
					}
				}
				return true;
			},

			// ── Order serialization on add/remove/reorder ──
			onaddfile: function () { syncOrderInput(queueType, this); },
			onremovefile: function () { syncOrderInput(queueType, this); },
			onreorderfiles: function () { syncOrderInput(queueType, this); },
			onupdatefiles: function () { syncOrderInput(queueType, this); },
		};
	}

	// ── Instance tracking ────────────────────────────────────────────────

	var _ponds = {};

	// ── Public API ────────────────────────────────────────────────────────

	/**
	 * Upgrade .tfe-file-picker inputs to FilePond instances.
	 * Called on page load and after HTMX swaps.
	 */
	window.XamxamInitFilePonds = function () {
		document.querySelectorAll(".tfe-file-picker").forEach(function (input) {
			// Canonical duplicate check: FilePond.find() is the authoritative source
			if (FilePond.find(input)) return;

			var id = input.id;
			var queueType = INPUT_ID_TO_TYPE[id];
			if (!queueType) {
				queueType = input.dataset.queueType || null;
			}
			if (!queueType) return;

			var options = buildFilePondOptions(queueType, input);
			if (!options) return;

			options.name = input.getAttribute("name") || input.name || "";

			var pond = FilePond.create(input, options);

			var key = id || queueType;
			_ponds[key] = pond;

			// Initial order serialization (for existing files in edit mode — none expected)
			syncOrderInput(queueType, pond);
		});
	};

	/**
	 * Destroy FilePond instances inside a given container element.
	 * Generic: handles ANY HTMX swap target, not just known IDs.
	 */
	function destroyFilePondsIn(el) {
		if (!el) return;
		el.querySelectorAll(".tfe-file-picker").forEach(function (input) {
			var pond = FilePond.find(input);
			if (pond) {
				try {
					// Remove order input before destroying
					var form = input.closest("form");
					if (form) {
						var id = input.id;
						var queueType = INPUT_ID_TO_TYPE[id] || input.dataset.queueType || null;
						if (queueType) {
							var orderInput = form.querySelector("input[name='queue_order[" + queueType + "]']");
							if (orderInput) orderInput.remove();
						}
					}
					pond.destroy();
				} catch (_) {}
			}
			// Clean up tracking
			if (input.id && _ponds[input.id]) {
				delete _ponds[input.id];
			}
		});
	}

	// ── HTMX integration ─────────────────────────────────────────────────

	/**
	 * Generic beforeSwap handler: destroy FilePonds in ANY swapped target.
	 * This prevents detached FilePond instances from leaking listeners.
	 */
	function onHtmxBeforeSwap(evt) {
		var target = evt.detail.target;
		if (target) {
			destroyFilePondsIn(target);
		}
	}

	// ── Bootstrap ─────────────────────────────────────────────────────────

	// Register FilePond plugins (idempotent)
	if (typeof FilePondPluginFileValidateType !== "undefined") {
		FilePond.registerPlugin(FilePondPluginFileValidateType);
	}
	if (typeof FilePondPluginFileValidateSize !== "undefined") {
		FilePond.registerPlugin(FilePondPluginFileValidateSize);
	}
	if (typeof FilePondPluginImagePreview !== "undefined") {
		FilePond.registerPlugin(FilePondPluginImagePreview);
	}
	if (typeof FilePondPluginImageExifOrientation !== "undefined") {
		FilePond.registerPlugin(FilePondPluginImageExifOrientation);
	}

	if (window.htmx) {
		window.htmx.on("htmx:beforeSwap", onHtmxBeforeSwap);
		window.htmx.on("htmx:afterSwap", function () {
			window.XamxamInitFilePonds();
		});
	}

	if (document.readyState === "loading") {
		document.addEventListener("DOMContentLoaded", function () {
			window.XamxamInitFilePonds();
		});
	} else {
		window.XamxamInitFilePonds();
	}

	// ── Mark form dirty on FilePond changes (beforeunload guard) ─────────
	document.addEventListener("FilePond:addfile", function () {
		window.__xamxamDirty = true;
	});

	document.addEventListener("submit", function (e) {
		var form = e.target;
		if (form && form.hasAttribute && form.hasAttribute("data-beforeunload-guard")) {
			window.__xamxamDirty = false;
		}
	});

})();
