(function () {
	'use strict';

	var board = document.querySelector('[data-tv-board]');
	if (!board || typeof window.LogisticaAdmin === 'undefined') {
		return;
	}

	var cfg = window.LogisticaAdmin;
	var pollSeconds = Math.max(8, parseInt(board.getAttribute('data-tv-poll'), 10) || 15);
	var state = {
		payload: null,
		filter: 'all',
		timerId: null,
		pollId: null
	};

	function escapeHtml(value) {
		return String(value == null ? '' : value)
			.replace(/&/g, '&amp;')
			.replace(/</g, '&lt;')
			.replace(/>/g, '&gt;')
			.replace(/"/g, '&quot;')
			.replace(/'/g, '&#39;');
	}

	function pad(n) {
		return (n < 10 ? '0' : '') + n;
	}

	function formatClockFromMinutes(total) {
		if (!Number.isFinite(total)) {
			return '—';
		}
		var abs = Math.abs(Math.round(total));
		var h = Math.floor(abs / 60);
		var m = abs % 60;
		var sign = total < 0 ? '-' : '';
		return sign + pad(h) + ':' + pad(m);
	}

	function formatWallClock(date) {
		return pad(date.getHours()) + ':' + pad(date.getMinutes()) + ':' + pad(date.getSeconds());
	}

	function nowMinutesLocal() {
		var d = new Date();
		return d.getHours() * 60 + d.getMinutes();
	}

	function post(action, fields) {
		var body = new FormData();
		body.append('action', action);
		body.append('nonce', cfg.tableroProduccionNonce || '');
		Object.keys(fields || {}).forEach(function (key) {
			body.append(key, fields[key] == null ? '' : String(fields[key]));
		});
		return fetch(cfg.ajaxUrl, {
			method: 'POST',
			credentials: 'same-origin',
			body: body
		}).then(function (res) {
			return res.json();
		});
	}

	function setRefreshStatus(text) {
		var el = board.querySelector('[data-tv-refresh-status]');
		if (el) {
			el.textContent = text;
		}
	}

	function updateClock() {
		var clock = board.querySelector('[data-tv-clock]');
		if (clock) {
			clock.textContent = formatWallClock(new Date());
		}
		tickTimers();
	}

	function tickTimers() {
		if (!state.payload || !Array.isArray(state.payload.jobs)) {
			return;
		}
		var now = nowMinutesLocal();
		board.querySelectorAll('[data-tv-card]').forEach(function (card) {
			var start = parseInt(card.getAttribute('data-timer-start'), 10);
			var end = parseInt(card.getAttribute('data-timer-end'), 10);
			var duration = parseInt(card.getAttribute('data-duration'), 10) || 0;
			if (!Number.isFinite(start) || !Number.isFinite(end)) {
				return;
			}
			var elapsed = now - start;
			var remaining = end - now;
			var overtime = duration > 0 && now > end && card.getAttribute('data-status') !== 'done';
			var elapsedEl = card.querySelector('[data-tv-elapsed]');
			var remainingEl = card.querySelector('[data-tv-remaining]');
			var remainingWrap = card.querySelector('[data-tv-remaining-wrap]');
			if (elapsedEl) {
				elapsedEl.textContent = formatClockFromMinutes(Math.max(0, elapsed));
			}
			if (remainingEl) {
				remainingEl.textContent = formatClockFromMinutes(remaining);
			}
			card.classList.toggle('is-overtime', !!overtime);
			if (remainingWrap) {
				remainingWrap.classList.toggle('is-overtime', !!overtime || remaining < 0);
			}
		});
	}

	function alertClass(alertKey) {
		return 'logistica-tv-board__alert-chip logistica-tv-board__alert-chip--' + (alertKey || 'programado');
	}

	function buildCard(job) {
		var priority = job.board_priority || 'plan_b';
		var alert = job.board_alert || 'programado';
		var alertLabels = (state.payload && state.payload.alerts) || {};
		var priorityLabels = (state.payload && state.payload.priorities) || {};
		var title = job.cliente || job.labor || job.referencia || 'Actividad';
		var metaParts = [];
		if (job.oc) {
			metaParts.push('OC ' + job.oc);
		}
		if (job.op) {
			metaParts.push('OP ' + job.op);
		}
		if (job.machine_label) {
			metaParts.push(job.machine_label);
		}
		if (job.referencia) {
			metaParts.push(job.referencia);
		}
		if (job.tamanos) {
			metaParts.push(job.tamanos);
		}

		return (
			'<article class="logistica-tv-card is-' + escapeHtml(priority) + (job.is_overtime ? ' is-overtime' : '') + '"' +
				' data-tv-card' +
				' data-id="' + escapeHtml(job.id) + '"' +
				' data-source="' + escapeHtml(job.source) + '"' +
				' data-machine="' + escapeHtml(job.machine) + '"' +
				' data-status="' + escapeHtml(job.status || '') + '"' +
				' data-timer-start="' + escapeHtml(job.timer_start) + '"' +
				' data-timer-end="' + escapeHtml(job.timer_end) + '"' +
				' data-duration="' + escapeHtml(job.duration_minutes) + '"' +
				' data-assigned="' + escapeHtml(job.assigned_person || '') + '"' +
				' data-priority="' + escapeHtml(priority) + '"' +
				' data-alert="' + escapeHtml(alert) + '"' +
			'>' +
				'<div class="logistica-tv-card__top">' +
					'<div>' +
						'<h4 class="logistica-tv-card__title">' + escapeHtml(title) + '</h4>' +
						'<div class="logistica-tv-card__meta">' + escapeHtml(metaParts.join(' · ')) + '</div>' +
					'</div>' +
					'<span class="logistica-tv-board__chip logistica-tv-board__chip--' + escapeHtml(priority) + '">' +
						escapeHtml(priorityLabels[priority] || priority) +
					'</span>' +
				'</div>' +
				'<div class="logistica-tv-card__person">' +
					escapeHtml(job.assigned_person ? ('Asignado: ' + job.assigned_person) : 'Sin persona asignada') +
				'</div>' +
				'<div class="' + alertClass(alert) + ' logistica-tv-card__alert">' +
					escapeHtml(alertLabels[alert] || alert) +
				'</div>' +
				'<div class="logistica-tv-card__timers">' +
					'<div class="logistica-tv-card__timer"><span>Inicio</span><strong>' + escapeHtml(job.start_clock || '—') + '</strong></div>' +
					'<div class="logistica-tv-card__timer"><span>Programado</span><strong>' + escapeHtml(job.programmed_label || '—') + '</strong></div>' +
					'<div class="logistica-tv-card__timer"><span>Transcurrido</span><strong data-tv-elapsed>' + escapeHtml(formatClockFromMinutes(job.elapsed_minutes || 0)) + '</strong></div>' +
					'<div class="logistica-tv-card__timer' + (job.is_overtime ? ' is-overtime' : '') + '" data-tv-remaining-wrap><span>Restante</span><strong data-tv-remaining>' + escapeHtml(formatClockFromMinutes(job.remaining_minutes || 0)) + '</strong></div>' +
				'</div>' +
			'</article>'
		);
	}

	function render(payload) {
		state.payload = payload;
		var etapa = payload.etapa || state.filter || 'all';
		state.filter = etapa;

		var filterSelect = board.querySelector('[data-tv-filter]');
		if (filterSelect && filterSelect.value !== etapa) {
			filterSelect.value = etapa;
		}

		var subtitle = board.querySelector('[data-tv-subtitle]');
		if (subtitle && payload.date) {
			var laneLabels = payload.lanes || {};
			var etapaLabel = etapa !== 'all' && laneLabels[etapa] ? (' · ' + laneLabels[etapa]) : '';
			subtitle.textContent = payload.date + etapaLabel;
		}

		board.classList.toggle('is-etapa-focused', etapa !== 'all');

		var total = payload.counts && payload.counts.total ? payload.counts.total : 0;
		var planA = payload.counts && payload.counts.plan_a ? payload.counts.plan_a : 0;
		var overtime = payload.counts && payload.counts.overtime ? payload.counts.overtime : 0;
		var statTotal = board.querySelector('[data-tv-stat="total"]');
		var statPlanA = board.querySelector('[data-tv-stat="plan_a"]');
		var statOt = board.querySelector('[data-tv-stat="overtime"]');
		if (statTotal) {
			statTotal.textContent = total + ' órdenes';
		}
		if (statPlanA) {
			statPlanA.textContent = planA + ' Plan A';
		}
		if (statOt) {
			statOt.textContent = overtime + ' fuera de tiempo';
		}

		board.querySelectorAll('[data-tv-lane]').forEach(function (laneEl) {
			var key = laneEl.getAttribute('data-tv-lane');
			var visible = etapa === 'all' || key === etapa;
			laneEl.hidden = !visible;
			laneEl.classList.toggle('is-hidden-etapa', !visible);
			laneEl.classList.toggle('is-active-etapa', visible && etapa !== 'all');

			var jobs = visible ? ((payload.jobs_by_lane && payload.jobs_by_lane[key]) || []) : [];
			var body = laneEl.querySelector('[data-tv-lane-body]');
			var count = laneEl.querySelector('[data-tv-lane-count]');
			if (count) {
				count.textContent = String(jobs.length);
			}
			if (body) {
				body.innerHTML = jobs.map(buildCard).join('');
			}
		});

		var empty = board.querySelector('[data-tv-empty]');
		if (empty) {
			empty.hidden = total > 0;
			empty.textContent = etapa === 'all'
				? 'No hay actividades programadas para hoy en la planeación.'
				: 'No hay actividades en esta etapa para hoy.';
		}
		tickTimers();
	}

	function refresh() {
		setRefreshStatus('Actualizando…');
		return post('logistica_get_tablero_produccion', {
			fecha: '',
			filter: state.filter,
			etapa: state.filter
		}).then(function (json) {
			if (!json || !json.success) {
				throw new Error((json && json.data && json.data.message) || 'No se pudo cargar el tablero');
			}
			render(json.data);
			setRefreshStatus('Auto · cada ' + pollSeconds + 's');
		}).catch(function (err) {
			setRefreshStatus(err.message || 'Error de actualización');
		});
	}

	function openEdit(card) {
		var dialog = board.querySelector('[data-tv-edit-dialog]');
		var form = board.querySelector('[data-tv-edit-form]');
		if (!dialog || !form) {
			return;
		}
		form.querySelector('[data-tv-edit="id"]').value = card.getAttribute('data-id') || '';
		form.querySelector('[data-tv-edit="source"]').value = card.getAttribute('data-source') || '';
		form.querySelector('[data-tv-edit="machine"]').value = card.getAttribute('data-machine') || '';
		form.querySelector('[data-tv-edit="assigned_person"]').value = card.getAttribute('data-assigned') || '';
		form.querySelector('[data-tv-edit="board_priority"]').value = card.getAttribute('data-priority') || 'plan_b';
		form.querySelector('[data-tv-edit="board_alert"]').value = card.getAttribute('data-alert') || '';
		if (typeof dialog.showModal === 'function') {
			dialog.showModal();
		}
	}

	function bind() {
		var filter = board.querySelector('[data-tv-filter]');
		if (filter) {
			filter.addEventListener('change', function () {
				state.filter = filter.value || 'all';
				refresh();
			});
		}

		var fsBtn = board.querySelector('[data-tv-fullscreen]');
		if (fsBtn) {
			fsBtn.addEventListener('click', function () {
				if (!document.fullscreenElement) {
					if (board.requestFullscreen) {
						board.requestFullscreen();
					}
				} else if (document.exitFullscreen) {
					document.exitFullscreen();
				}
			});
		}

		board.addEventListener('click', function (event) {
			var closeBtn = event.target.closest('[data-tv-edit-close]');
			if (closeBtn) {
				var dialog = board.querySelector('[data-tv-edit-dialog]');
				if (dialog && dialog.open) {
					dialog.close();
				}
				return;
			}
			var card = event.target.closest('[data-tv-card]');
			if (card) {
				openEdit(card);
			}
		});

		var form = board.querySelector('[data-tv-edit-form]');
		if (form) {
			form.addEventListener('submit', function (event) {
				event.preventDefault();
				var fields = {
					id: form.querySelector('[data-tv-edit="id"]').value,
					source: form.querySelector('[data-tv-edit="source"]').value,
					machine: form.querySelector('[data-tv-edit="machine"]').value,
					assigned_person: form.querySelector('[data-tv-edit="assigned_person"]').value,
					board_priority: form.querySelector('[data-tv-edit="board_priority"]').value,
					board_alert: form.querySelector('[data-tv-edit="board_alert"]').value
				};
				setRefreshStatus('Guardando…');
				post('logistica_save_tablero_produccion_job', fields).then(function (json) {
					if (!json || !json.success) {
						throw new Error((json && json.data && json.data.message) || 'No se pudo guardar');
					}
					var dialog = board.querySelector('[data-tv-edit-dialog]');
					if (dialog && dialog.open) {
						dialog.close();
					}
					return refresh();
				}).catch(function (err) {
					setRefreshStatus(err.message || 'Error al guardar');
				});
			});
		}
	}

	bind();
	updateClock();
	state.timerId = window.setInterval(updateClock, 1000);
	refresh();
	state.pollId = window.setInterval(refresh, pollSeconds * 1000);
})();
