/**
 * GoValid QR Analytics — Charts, Map, and QR Drilldown.
 *
 * @package GoValid_QR
 */

/* global jQuery, govalidQR, Chart, L */
(function ($) {
	'use strict';

	var charts = {};
	var ddCharts = {};
	var map = null;
	var markerGroup = null;

	/* ---------- palette ---------- */
	var PALETTE = [
		'#2563eb', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6',
		'#06b6d4', '#ec4899', '#14b8a6', '#f97316', '#6366f1'
	];

	/* ---------- helpers ---------- */
	function num(v) {
		return (v || 0).toLocaleString();
	}

	function getFlagEmoji(cc) {
		if (!cc || cc.length !== 2) return '';
		var codePoints = cc.toUpperCase().split('').map(function (c) {
			return 0x1f1e6 - 65 + c.charCodeAt(0);
		});
		return String.fromCodePoint.apply(null, codePoints);
	}

	/* ---------- init ---------- */
	function init() {
		if ( ! govalidQR.isConnected ) {
			showEmpty();
			return;
		}
		$.ajax({
			url: govalidQR.restUrl + 'analytics',
			method: 'GET',
			beforeSend: function (xhr) {
				xhr.setRequestHeader('X-WP-Nonce', govalidQR.nonce);
			},
			success: function (res) {
				var d = (res && res.data) ? res.data : res;
				if (!d || !d.summary) {
					showEmpty();
					return;
				}
				removeSkeleton();
				renderSummary(d.summary);
				renderMap(d.locations || []);
				renderDailyTrend(d.daily_trend || []);
				renderCountries(d.countries || []);
				renderDevices(d.devices || {});
				renderQRTypes(d.qr_by_type || {});
				renderTopQR(d.top_qr_codes || []);
			},
			error: function () {
				showEmpty();
			}
		});

		$('#drilldown-close').on('click', function () {
			$('#qr-drilldown-card').slideUp(200);
		});
	}

	function removeSkeleton() {
		$('.govalid-stat-card').removeClass('govalid-shimmer');
	}

	function showEmpty() {
		removeSkeleton();
		$('#stat-qr-codes, #stat-total-scans, #stat-month-scans, #stat-countries').text('0');
	}

	/* ---------- summary ---------- */
	function renderSummary(s) {
		$('#stat-qr-codes').text(num(s.total_qr_codes));
		$('#stat-total-scans').text(num(s.total_scans));
		$('#stat-month-scans').text(num(s.scans_this_month));
		$('#stat-countries').text(num(s.unique_countries));
	}

	/* ---------- map ---------- */
	function renderMap(locations) {
		if (!locations.length) {
			$('#govalid-analytics-map').hide();
			$('#map-empty').show();
			return;
		}

		map = L.map('govalid-analytics-map', { zoomControl: true, scrollWheelZoom: true }).setView([0, 20], 2);

		/* --- Tile layers --- */
		var streetLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
			attribution: '&copy; OpenStreetMap',
			maxZoom: 19
		});

		var lightLayer = L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
			attribution: '&copy; OpenStreetMap &copy; CARTO',
			subdomains: 'abcd',
			maxZoom: 19
		});

		var darkLayer = L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', {
			attribution: '&copy; OpenStreetMap &copy; CARTO',
			subdomains: 'abcd',
			maxZoom: 19
		});

		var satelliteLayer = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
			attribution: '&copy; Esri &mdash; Earthstar Geographics',
			maxZoom: 18
		});

		streetLayer.addTo(map);

		L.control.layers({
			'Street': streetLayer,
			'Light': lightLayer,
			'Dark': darkLayer,
			'Satellite': satelliteLayer
		}, null, { position: 'topright' }).addTo(map);

		/* --- Zoom reset control --- */
		var ZoomReset = L.Control.extend({
			options: { position: 'topleft' },
			onAdd: function () {
				var container = L.DomUtil.create('div', 'leaflet-bar leaflet-control');
				var btn = L.DomUtil.create('a', 'govalid-zoom-reset', container);
				btn.innerHTML = '<span class="dashicons dashicons-fullscreen-exit-alt"></span>';
				btn.title = 'Fit all markers';
				btn.href = '#';
				L.DomEvent.on(btn, 'click', function (e) {
					L.DomEvent.preventDefault(e);
					if (markerGroup && markerGroup.getLayers().length) {
						map.fitBounds(markerGroup.getBounds(), { padding: [50, 50] });
					} else {
						map.setView([0, 20], 2);
					}
				});
				return container;
			}
		});
		new ZoomReset().addTo(map);

		/* --- MarkerCluster group --- */
		markerGroup = L.markerClusterGroup({
			showCoverageOnHover: true,
			zoomToBoundsOnClick: true,
			spiderfyOnMaxZoom: true,
			removeOutsideVisibleBounds: true,
			disableClusteringAtZoom: 16,
			maxClusterRadius: 80,
			iconCreateFunction: function (cluster) {
				var count = cluster.getChildCount();
				var size = count < 10 ? 'small' : count < 50 ? 'medium' : 'large';
				return new L.DivIcon({
					html: '<div><span>' + count + '</span></div>',
					className: 'marker-cluster marker-cluster-' + size,
					iconSize: new L.Point(40, 40)
				});
			}
		});

		/* --- Custom marker icon --- */
		function pinIcon() {
			return L.divIcon({
				className: 'govalid-div-icon',
				html: '<div class="govalid-marker-pin"></div><span class="dashicons dashicons-location"></span>',
				iconSize: [28, 40],
				iconAnchor: [14, 40],
				popupAnchor: [0, -36]
			});
		}

		/* --- Search control --- */
		var allMarkers = [];
		var QRSearch = L.Control.extend({
			options: { position: 'bottomleft' },
			onAdd: function () {
				var self = this;
				var container = L.DomUtil.create('div', 'govalid-map-search');

				var input = L.DomUtil.create('input', '', container);
				input.type = 'text';
				input.placeholder = 'Search QR codes...';

				var results = L.DomUtil.create('div', 'govalid-map-search-results', container);

				L.DomEvent.on(input, 'input', function () {
					var q = input.value.toLowerCase().trim();
					if (q.length < 2) { results.style.display = 'none'; return; }

					var matches = allMarkers.filter(function (m) {
						return m._qrName.toLowerCase().indexOf(q) !== -1 ||
							   m._qrLoc.toLowerCase().indexOf(q) !== -1;
					});

					results.innerHTML = '';
					results.style.display = 'block';

					if (!matches.length) {
						results.innerHTML = '<div class="govalid-map-search-empty">No results for "' + escapeHtml(q) + '"</div>';
						return;
					}

					matches.slice(0, 20).forEach(function (m) {
						var item = L.DomUtil.create('div', 'govalid-map-search-item', results);
						item.innerHTML = '<span class="dashicons dashicons-screenoptions"></span>' +
							'<span class="govalid-search-name">' + escapeHtml(m._qrName) + '</span>' +
							'<span class="govalid-search-loc">' + escapeHtml(m._qrLoc) + '</span>';
						L.DomEvent.on(item, 'click', function () {
							map.setView(m.getLatLng(), 16);
							m.openPopup();
							$(results).find('.active').removeClass('active');
							item.classList.add('active');
						});
					});
				});

				L.DomEvent.disableClickPropagation(container);
				L.DomEvent.disableScrollPropagation(container);
				return container;
			}
		});
		new QRSearch().addTo(map);

		/* --- Add markers --- */
		var scansLabel = (govalidQR.i18n && govalidQR.i18n.scans_label) ? govalidQR.i18n.scans_label : 'scans';

		locations.forEach(function (loc) {
			if (!loc.latitude || !loc.longitude) { return; }

			var popup = '<div class="govalid-popup-header"><span class="dashicons dashicons-screenoptions"></span>' + escapeHtml(loc.qr_code_name || 'QR') + '</div>' +
				'<div class="govalid-popup-body">' +
				'<p><span class="dashicons dashicons-location"></span><strong>' + escapeHtml(loc.location_name || 'Unknown') + '</strong></p>' +
				'<p><span class="dashicons dashicons-chart-bar"></span>' + loc.scan_count + ' ' + scansLabel + '</p>' +
				'</div>' +
				'<div class="govalid-popup-footer">' + escapeHtml(loc.qr_code_name || '') + '</div>';

			var marker = L.marker([loc.latitude, loc.longitude], { icon: pinIcon() })
				.bindPopup(popup, { className: 'govalid-map-popup', closeButton: true, maxWidth: 280 });

			marker._qrName = loc.qr_code_name || '';
			marker._qrLoc = loc.location_name || '';

			allMarkers.push(marker);
			markerGroup.addLayer(marker);
		});

		markerGroup.addTo(map);

		if (allMarkers.length) {
			var bounds = allMarkers.map(function (m) { return m.getLatLng(); });
			map.fitBounds(bounds, { padding: [50, 50] });
		}
	}

	/* ---------- daily trend (line) ---------- */
	function renderDailyTrend(trend) {
		if (!trend.length) {
			$('#chart-daily-trend').closest('.govalid-chart-wrap').hide();
			$('#trend-empty').show();
			return;
		}

		var ctx = document.getElementById('chart-daily-trend').getContext('2d');
		charts.dailyTrend = new Chart(ctx, {
			type: 'line',
			data: {
				labels: trend.map(function (t) { return t.date; }),
				datasets: [{
					label: govalidQR.i18n && govalidQR.i18n.scans_label ? govalidQR.i18n.scans_label : 'Scans',
					data: trend.map(function (t) { return t.count; }),
					borderColor: '#2563eb',
					backgroundColor: 'rgba(37,99,235,0.08)',
					fill: true,
					tension: 0.35,
					pointRadius: 2,
					pointHoverRadius: 5
				}]
			},
			options: {
				responsive: true,
				maintainAspectRatio: false,
				plugins: { legend: { display: false } },
				scales: {
					x: { grid: { display: false }, ticks: { maxTicksLimit: 8 } },
					y: { beginAtZero: true, ticks: { precision: 0 } }
				}
			}
		});
	}

	/* ---------- countries (doughnut) ---------- */
	function renderCountries(countries) {
		if (!countries.length) {
			$('#chart-countries').closest('.govalid-chart-wrap').hide();
			$('#countries-empty').show();
			return;
		}

		var top = countries.slice(0, 8);
		var ctx = document.getElementById('chart-countries').getContext('2d');
		charts.countries = new Chart(ctx, {
			type: 'doughnut',
			data: {
				labels: top.map(function (c) { return getFlagEmoji(c.country_code) + ' ' + c.country_code; }),
				datasets: [{
					data: top.map(function (c) { return c.count; }),
					backgroundColor: PALETTE.slice(0, top.length)
				}]
			},
			options: {
				responsive: true,
				maintainAspectRatio: false,
				plugins: {
					legend: { position: 'right', labels: { boxWidth: 14, padding: 10 } }
				}
			}
		});
	}

	/* ---------- devices (horizontal bar) ---------- */
	function renderDevices(devices) {
		var platforms = devices.platforms || [];
		var browsers = devices.browsers || [];
		var items = platforms.concat(browsers).sort(function (a, b) { return b.count - a.count; }).slice(0, 10);

		if (!items.length) {
			$('#chart-devices').closest('.govalid-chart-wrap').hide();
			$('#devices-empty').show();
			return;
		}

		var ctx = document.getElementById('chart-devices').getContext('2d');
		charts.devices = new Chart(ctx, {
			type: 'bar',
			data: {
				labels: items.map(function (i) { return i.name; }),
				datasets: [{
					data: items.map(function (i) { return i.count; }),
					backgroundColor: PALETTE.slice(0, items.length)
				}]
			},
			options: {
				indexAxis: 'y',
				responsive: true,
				maintainAspectRatio: false,
				plugins: { legend: { display: false } },
				scales: {
					x: { beginAtZero: true, ticks: { precision: 0 } },
					y: { grid: { display: false } }
				}
			}
		});
	}

	/* ---------- QR types (doughnut) ---------- */
	function renderQRTypes(types) {
		var labels = Object.keys(types);
		var values = Object.values(types);

		if (!labels.length || values.every(function (v) { return v === 0; })) {
			$('#chart-qr-types').closest('.govalid-chart-wrap').hide();
			$('#types-empty').show();
			return;
		}

		var ctx = document.getElementById('chart-qr-types').getContext('2d');
		charts.qrTypes = new Chart(ctx, {
			type: 'doughnut',
			data: {
				labels: labels,
				datasets: [{
					data: values,
					backgroundColor: PALETTE.slice(0, labels.length)
				}]
			},
			options: {
				responsive: true,
				maintainAspectRatio: false,
				plugins: {
					legend: { position: 'right', labels: { boxWidth: 14, padding: 10 } }
				}
			}
		});
	}

	/* ---------- top QR codes table ---------- */
	function renderTopQR(topQR) {
		if (!topQR.length) {
			$('#top-qr-empty').show();
			return;
		}

		var $body = $('#top-qr-body');
		$body.empty();

		topQR.forEach(function (qr) {
			var $row = $('<tr>');
			$row.append($('<td>').text(qr.name || '—'));
			$row.append($('<td>').text(qr.type || '—'));
			$row.append($('<td style="text-align:right;">').text(num(qr.scans)));
			var $btn = $('<button type="button" class="button button-small govalid-drilldown-btn">')
				.text(govalidQR.i18n && govalidQR.i18n.view_detail ? govalidQR.i18n.view_detail : 'View')
				.data('uuid', qr.uuid)
				.data('name', qr.name);
			$row.append($('<td style="text-align:center;">').append($btn));
			$body.append($row);
		});

		$('#top-qr-table').show();

		$body.on('click', '.govalid-drilldown-btn', function () {
			var uuid = $(this).data('uuid');
			var name = $(this).data('name');
			loadDrilldown(uuid, name);
		});
	}

	/* ---------- drilldown ---------- */
	function loadDrilldown(uuid, name) {
		$('#drilldown-title').text(name || 'QR Code Detail');
		$('#qr-drilldown-card').slideDown(200);
		$('#drilldown-loading').show();
		$('#drilldown-content').hide();

		// Scroll to drilldown
		$('html, body').animate({ scrollTop: $('#qr-drilldown-card').offset().top - 40 }, 300);

		$.ajax({
			url: govalidQR.restUrl + 'analytics/' + encodeURIComponent(uuid),
			method: 'GET',
			beforeSend: function (xhr) {
				xhr.setRequestHeader('X-WP-Nonce', govalidQR.nonce);
			},
			success: function (res) {
				$('#drilldown-loading').hide();
				$('#drilldown-content').show();

				var d = (res && res.data) ? res.data : res;
				renderDrilldownContent(d);
			},
			error: function () {
				$('#drilldown-loading').html('<p style="color:#ef4444;">' +
					(govalidQR.i18n && govalidQR.i18n.error ? govalidQR.i18n.error : 'An error occurred.') +
					'</p>');
			}
		});
	}

	function renderDrilldownContent(d) {
		$('#dd-total-scans').text(num(d.total_scans));
		$('#dd-unique-scanners').text(num(d.unique_scanners));

		// Destroy previous drilldown charts
		if (ddCharts.daily) ddCharts.daily.destroy();
		if (ddCharts.geo) ddCharts.geo.destroy();

		// Daily scans chart
		var daily = d.daily_scans || [];
		if (daily.length) {
			var ctx1 = document.getElementById('dd-chart-daily').getContext('2d');
			ddCharts.daily = new Chart(ctx1, {
				type: 'line',
				data: {
					labels: daily.map(function (i) { return i.date; }),
					datasets: [{
						data: daily.map(function (i) { return i.total; }),
						borderColor: '#2563eb',
						backgroundColor: 'rgba(37,99,235,0.08)',
						fill: true,
						tension: 0.35,
						pointRadius: 2
					}]
				},
				options: {
					responsive: true,
					maintainAspectRatio: false,
					plugins: { legend: { display: false } },
					scales: {
						x: { grid: { display: false }, ticks: { maxTicksLimit: 8 } },
						y: { beginAtZero: true, ticks: { precision: 0 } }
					}
				}
			});
		}

		// Geographic distribution chart
		var geo = d.geographic_distribution || [];
		if (geo.length) {
			var top = geo.slice(0, 6);
			var ctx2 = document.getElementById('dd-chart-geo').getContext('2d');
			ddCharts.geo = new Chart(ctx2, {
				type: 'doughnut',
				data: {
					labels: top.map(function (g) { return getFlagEmoji(g.country_code) + ' ' + (g.country || g.country_code); }),
					datasets: [{
						data: top.map(function (g) { return g.scan_count; }),
						backgroundColor: PALETTE.slice(0, top.length)
					}]
				},
				options: {
					responsive: true,
					maintainAspectRatio: false,
					plugins: { legend: { position: 'right', labels: { boxWidth: 14, padding: 10 } } }
				}
			});
		}
	}

	/* ---------- escape ---------- */
	function escapeHtml(str) {
		var div = document.createElement('div');
		div.appendChild(document.createTextNode(str));
		return div.innerHTML;
	}

	/* ---------- boot ---------- */
	$(document).ready(init);

})(jQuery);
