/**
 * TrustLens Chart Theme
 *
 * Shared Chart.js palette, typography, tooltip, and dataset helpers so every
 * chart in the plugin reads as one product. Colors match the TrustLens website
 * design system (emerald primary + slate ink). All chart scripts depend on
 * this file and call TrustLensChartTheme.applyDefaults() before constructing
 * new Chart() instances.
 *
 * Loaded as a dependency before command-center-charts.js,
 * chargeback-monitor.js, and card-testing-admin-pro.js.
 *
 * @package TrustLens
 * @since   1.2.5
 */

/* global Chart */

(function (root) {
	'use strict';

	if (root.TrustLensChartTheme) {
		return;
	}

	// Brand palette — mirrors --tl-* tokens used on webstepper.io/trustlens.
	var COLORS = {
		emerald:      '#10b981',
		emeraldDark:  '#059669',
		emeraldSoft:  'rgba(16, 185, 129, 0.10)',
		ink:          '#0f172a', // slate-950
		slate700:     '#334155',
		slate600:     '#475569',
		slate500:     '#64748b',
		slate300:     '#cbd5e1',
		slate200:     '#e2e8f0',
		slate100:     '#f8fafc',
		white:        '#ffffff',

		// Semantic — softened from Bootstrap-era to a calmer Tailwind range so
		// the dashboard doesn't shout at the merchant.
		risk:         '#ef4444', // red-500
		riskSoft:     'rgba(239, 68, 68, 0.12)',
		warn:         '#f59e0b', // amber-500
		warnSoft:     'rgba(245, 158, 11, 0.14)',
		caution:      '#facc15', // yellow-400
		info:         '#3b82f6', // blue-500
		infoSoft:     'rgba(59, 130, 246, 0.10)'
	};

	var FONT_STACK = 'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';

	var applied = false;

	/**
	 * Apply global Chart.js defaults. Safe to call multiple times — only the
	 * first call mutates Chart.defaults; subsequent calls no-op.
	 */
	function applyDefaults() {
		if (applied || typeof Chart === 'undefined') {
			return;
		}
		applied = true;

		// Typography — slightly larger base size so labels read clearly on
		// retina without zooming.
		Chart.defaults.font.family = FONT_STACK;
		Chart.defaults.font.size   = 12;
		Chart.defaults.font.weight = '500';
		Chart.defaults.color       = COLORS.slate600;

		// Tooltips — light card with subtle shadow, not the default black.
		Chart.defaults.plugins.tooltip.backgroundColor = COLORS.white;
		Chart.defaults.plugins.tooltip.titleColor      = COLORS.ink;
		Chart.defaults.plugins.tooltip.bodyColor       = COLORS.slate700;
		Chart.defaults.plugins.tooltip.borderColor     = COLORS.slate200;
		Chart.defaults.plugins.tooltip.borderWidth     = 1;
		Chart.defaults.plugins.tooltip.cornerRadius    = 8;
		Chart.defaults.plugins.tooltip.padding         = { top: 10, right: 14, bottom: 10, left: 14 };
		Chart.defaults.plugins.tooltip.titleFont       = { weight: '600', size: 13, family: FONT_STACK };
		Chart.defaults.plugins.tooltip.bodyFont        = { weight: '500', size: 12, family: FONT_STACK };
		Chart.defaults.plugins.tooltip.boxPadding      = 6;
		Chart.defaults.plugins.tooltip.usePointStyle   = true;
		Chart.defaults.plugins.tooltip.displayColors   = true;
		Chart.defaults.plugins.tooltip.caretSize       = 6;

		// Legend — circle markers, generous spacing, slate ink.
		Chart.defaults.plugins.legend.labels.usePointStyle    = true;
		Chart.defaults.plugins.legend.labels.pointStyle       = 'circle';
		Chart.defaults.plugins.legend.labels.pointStyleWidth  = 10;
		Chart.defaults.plugins.legend.labels.boxWidth         = 10;
		Chart.defaults.plugins.legend.labels.boxHeight        = 10;
		Chart.defaults.plugins.legend.labels.useBorderRadius  = true;
		Chart.defaults.plugins.legend.labels.borderRadius     = 999;
		Chart.defaults.plugins.legend.labels.padding          = 18;
		Chart.defaults.plugins.legend.labels.color            = COLORS.slate700;
		Chart.defaults.plugins.legend.labels.font             = { weight: '500', size: 12, family: FONT_STACK };

		// Bars — softer rounded caps.
		Chart.defaults.elements.bar.borderRadius        = 6;
		Chart.defaults.elements.bar.borderSkipped       = false;

		// Lines — thinner stroke, smoother curve, no point clutter.
		Chart.defaults.elements.line.borderWidth        = 2;
		Chart.defaults.elements.line.tension            = 0.35;
		Chart.defaults.elements.point.radius            = 0;
		Chart.defaults.elements.point.hoverRadius       = 5;
		Chart.defaults.elements.point.hoverBorderWidth  = 2;
		Chart.defaults.elements.point.hoverBackgroundColor = COLORS.white;

		// Grid & axes — slate-tinted, barely-there grid lines, no axis borders.
		Chart.defaults.scale.grid.color       = 'rgba(15, 23, 42, 0.06)';
		Chart.defaults.scale.grid.drawTicks   = false;
		Chart.defaults.scale.border           = { display: false };
		Chart.defaults.scale.ticks.color      = COLORS.slate500;
		Chart.defaults.scale.ticks.padding    = 8;
		Chart.defaults.scale.ticks.font       = { weight: '500', size: 11, family: FONT_STACK };

		// Animation — quicker, snappier.
		Chart.defaults.animation.duration     = 600;
		Chart.defaults.animation.easing       = 'easeOutQuart';
		Chart.defaults.animations.colors      = { type: 'color', duration: 300, easing: 'linear' };
		Chart.defaults.transitions.active.animation.duration = 200;

		// Force circle legend markers across all chart types.
		var defaultGenerateLegendLabels = Chart.defaults.plugins.legend.labels.generateLabels;
		Chart.defaults.plugins.legend.labels.generateLabels = function (chart) {
			var labels = defaultGenerateLegendLabels(chart);
			return labels.map(function (label) {
				var fill = label.fillStyle || label.strokeStyle;
				return Object.assign({}, label, {
					pointStyle:   'circle',
					lineWidth:    0,
					strokeStyle:  fill,
					fillStyle:    fill,
					borderRadius: 999
				});
			});
		};
	}

	/**
	 * Build a vertical linear gradient that fades the given hex/rgba color
	 * from `topAlpha` at y=0 down to 0 at y=height. Use for line-chart fills.
	 */
	function verticalGradient(ctx, color, topAlpha, height) {
		topAlpha = (typeof topAlpha === 'number') ? topAlpha : 0.22;
		height   = height || 320;
		var rgb  = hexToRgb(color);
		if (!rgb) {
			return color;
		}
		var gradient = ctx.createLinearGradient(0, 0, 0, height);
		gradient.addColorStop(0,    'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + topAlpha + ')');
		gradient.addColorStop(0.6,  'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + (topAlpha * 0.25) + ')');
		gradient.addColorStop(1,    'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ', 0)');
		return gradient;
	}

	function hexToRgb(hex) {
		if (typeof hex !== 'string') { return null; }
		var m = hex.replace('#', '').match(/^([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i);
		if (!m) { return null; }
		return { r: parseInt(m[1], 16), g: parseInt(m[2], 16), b: parseInt(m[3], 16) };
	}

	/**
	 * Build a line dataset with TrustLens defaults pre-applied. Caller passes
	 * { label, data, color, ctx, fill?, dashed? } and overrides anything they
	 * want. Use this so every line chart looks identical out of the box.
	 */
	function lineDataset(opts) {
		var color = opts.color || COLORS.emerald;
		var fill  = opts.fill !== false;
		var dataset = {
			label:                opts.label,
			data:                 opts.data,
			borderColor:          color,
			backgroundColor:      fill && opts.ctx ? verticalGradient(opts.ctx, color, opts.topAlpha || 0.22) : 'transparent',
			fill:                 fill,
			tension:              0.35,
			borderWidth:          2,
			pointRadius:          0,
			pointHoverRadius:     5,
			pointHoverBorderColor: color,
			pointHoverBackgroundColor: COLORS.white,
			pointHoverBorderWidth: 2
		};
		if (opts.dashed) {
			dataset.borderDash  = [6, 5];
			dataset.borderWidth = 1.25;
			dataset.borderColor = opts.color || COLORS.slate300;
			dataset.fill        = false;
			dataset.pointHoverRadius = 0;
		}
		return dataset;
	}

	/**
	 * Build a bar dataset with TrustLens defaults pre-applied.
	 */
	function barDataset(opts) {
		return {
			label:           opts.label,
			data:            opts.data,
			backgroundColor: opts.backgroundColor || COLORS.emerald,
			borderRadius:    typeof opts.borderRadius === 'number' ? opts.borderRadius : 6,
			borderSkipped:   false,
			maxBarThickness: opts.maxBarThickness || 32
		};
	}

	/**
	 * Map a value to a risk-color tier. Used by hourly / category charts so
	 * intensity reads consistently: low = emerald, medium = amber, high = red.
	 */
	function riskScale(value, thresholds) {
		thresholds = thresholds || { high: 30, medium: 15 };
		if (value >= thresholds.high) {
			return COLORS.risk;
		}
		if (value >= thresholds.medium) {
			return COLORS.warn;
		}
		return COLORS.emerald;
	}

	/**
	 * Build an intensity gradient palette where the lowest value reads slate
	 * and the highest reads emerald — gives bar charts a heat-map feel without
	 * shouting risk-red at routine traffic.
	 */
	function intensityPalette(values) {
		var max = Math.max.apply(null, values) || 1;
		return values.map(function (v) {
			var t       = v / max;
			var emerald = hexToRgb(COLORS.emerald);
			var slate   = hexToRgb(COLORS.slate200);
			var r = Math.round(slate.r + (emerald.r - slate.r) * t);
			var g = Math.round(slate.g + (emerald.g - slate.g) * t);
			var b = Math.round(slate.b + (emerald.b - slate.b) * t);
			return 'rgba(' + r + ',' + g + ',' + b + ',' + (0.55 + 0.45 * t).toFixed(2) + ')';
		});
	}

	/**
	 * "No data yet" plugin — when a chart has no datapoints, render a single
	 * centered slate message instead of an empty canvas. Register once via
	 * Chart.register(TrustLensChartTheme.noDataPlugin).
	 */
	var noDataPlugin = {
		id: 'trustlensNoData',
		afterDraw: function (chart) {
			var datasets = chart.data && chart.data.datasets ? chart.data.datasets : [];
			var total = datasets.reduce(function (sum, d) {
				return sum + (d.data || []).reduce(function (a, v) {
					return a + (typeof v === 'number' ? Math.abs(v) : 0);
				}, 0);
			}, 0);
			if (total > 0) {
				return;
			}
			var ctx     = chart.ctx;
			var width   = chart.width;
			var height  = chart.height;
			var message = (chart.options.plugins && chart.options.plugins.trustlensNoData && chart.options.plugins.trustlensNoData.message) || 'No data yet';

			ctx.save();
			ctx.fillStyle    = COLORS.slate500;
			ctx.textAlign    = 'center';
			ctx.textBaseline = 'middle';
			ctx.font         = '600 13px ' + FONT_STACK;
			ctx.fillText(message, width / 2, height / 2);
			ctx.restore();
		}
	};

	root.TrustLensChartTheme = {
		COLORS:           COLORS,
		FONT_STACK:       FONT_STACK,
		applyDefaults:    applyDefaults,
		verticalGradient: verticalGradient,
		hexToRgb:         hexToRgb,
		lineDataset:      lineDataset,
		barDataset:       barDataset,
		riskScale:        riskScale,
		intensityPalette: intensityPalette,
		noDataPlugin:     noDataPlugin
	};

	// Apply defaults eagerly so consumers can construct charts without an
	// explicit applyDefaults() call.
	applyDefaults();
}(typeof window !== 'undefined' ? window : this));
