import '../scss/module-speed.scss';

/**
 * Monitor.Cat — Speed Optimizer module.
 *
 * Wizard-style flow: auto-scans on load, renders categorized
 * results with score ring, tabbed views, active optimizations
 * toggles, database cleanup, and actionable fix tips.
 *
 * @package MonitorCat
 */
( function () {
	'use strict';

	var api = window.MonitorCatAdmin;
	var i18n = window.MonitorCatSpeedI18n || {};

	// ── Analyzer category mapping ────────────────────────────────────
	var CATEGORIES = {
		performance: {
			page_weight:   { icon: 'fa-file-code',       color: 'primary',  label: i18n.labelPageWeight || 'Page Weight' },
			image_opt:     { icon: 'fa-images',           color: 'mint',     label: i18n.labelImageOptimization || 'Image Optimization' },
			assets:        { icon: 'fa-cubes',            color: 'lavender', label: i18n.labelCssJavascript || 'CSS & JavaScript' },
		},
		infrastructure: {
			cache:         { icon: 'fa-database',         color: 'cyan',     label: i18n.labelCaching || 'Caching' },
			compression:   { icon: 'fa-compress',         color: 'primary',  label: i18n.labelCompression || 'Compression' },
			response_time: { icon: 'fa-stopwatch',        color: 'coral',    label: i18n.labelResponseTime || 'Response Time' },
		},
		database: {
			database:      { icon: 'fa-server',           color: 'lavender', label: i18n.labelDatabaseHealth || 'Database Health' },
		},
	};

	var STATUS_LABELS = {
		good:     i18n.statusGood || 'Passing',
		warning:  i18n.statusWarning || 'Needs Work',
		critical: i18n.statusCritical || 'Fix This',
	};

	var STATUS_BADGE = {
		good:     'success',
		warning:  'warning',
		critical: 'error',
	};

	var STATUS_ICON = {
		good:     'fa-circle-check',
		warning:  'fa-triangle-exclamation',
		critical: 'fa-circle-xmark',
	};

	// ── Fix tips per check label ────────────────────────────────────
	var FIX_TIPS = {
		'HTML Size':             { tip: i18n.tipHtmlSize || 'Reduce HTML size by removing unnecessary inline content and using external CSS/JS files.', action: 'optimizations', actionLabel: i18n.actionEnableHeadCleanup || 'Enable Head Cleanup' },
		'Inline Scripts':        { tip: i18n.tipInlineScripts || 'Move inline scripts to external files and use defer loading. Enable Script Defer optimization.', action: 'optimizations', actionLabel: i18n.actionEnableScriptDefer || 'Enable Script Defer' },
		'Inline Styles':         { tip: i18n.tipInlineStyles || 'Move inline styles to external CSS files to improve caching and reduce page weight.', action: 'none' },
		'Resource Hints':        { tip: i18n.tipResourceHints || 'Enable Monitor.Cat Resource Hints optimization to automatically add preconnect for external services.', action: 'optimizations', actionLabel: i18n.actionEnableResourceHints || 'Enable Resource Hints' },
		'Total Images':          { tip: i18n.tipTotalImages || 'Consider reducing the number of images or using CSS sprites for decorative elements.', action: 'none' },
		'WebP Coverage':         { tip: i18n.tipWebpCoverage || 'Convert images to WebP format. Install an image optimization plugin like Imagify or ShortPixel.', action: 'none' },
		'Lazy Loading':          { tip: i18n.tipLazyLoading || 'Enable Monitor.Cat Lazy Media optimization for automatic iframe lazy loading and async image decoding.', action: 'optimizations', actionLabel: i18n.actionEnableLazyMedia || 'Enable Lazy Media' },
		'Optimization Plugin':   { tip: i18n.tipOptimizationPlugin || 'Install an image optimization plugin (Imagify, ShortPixel, EWWW, or Smush) for automatic compression.', action: 'none' },
		'CSS Files':             { tip: i18n.tipCssFiles || 'Reduce the number of CSS files by combining stylesheets or removing unused plugins.', action: 'none' },
		'JS Files':              { tip: i18n.tipJsFiles || 'Reduce the number of JavaScript files. Deactivate unused plugins to eliminate unnecessary scripts.', action: 'none' },
		'Render-Blocking Scripts': { tip: i18n.tipRenderBlocking || 'Enable Monitor.Cat Script Defer to automatically add defer attributes to render-blocking scripts.', action: 'optimizations', actionLabel: i18n.actionEnableScriptDefer || 'Enable Script Defer' },
		'jQuery':                { tip: i18n.tipJquery || 'Consider plugins that don\'t depend on jQuery. Enable jQuery Migrate removal for a lighter footprint.', action: 'optimizations', actionLabel: i18n.actionSettings || 'Settings' },
		'Total Assets':          { tip: i18n.tipTotalAssets || 'Reduce total assets by deactivating unused plugins and combining where possible.', action: 'none' },
		'Object Cache':          { tip: i18n.tipObjectCache || 'Install Redis or Memcached and a persistent object cache plugin for faster database queries.', action: 'none' },
		'Page Cache':            { tip: i18n.tipPageCache || 'Install a caching plugin (WP Super Cache, W3 Total Cache, WP Rocket, or LiteSpeed Cache).', action: 'none' },
		'Browser Cache':         { tip: i18n.tipBrowserCache || 'Add Cache-Control headers via your web server config or .htaccess for static assets.', action: 'none' },
		'HTTP Compression':      { tip: i18n.tipHttpCompression || 'Enable GZIP or Brotli compression on your web server for significantly smaller transfers.', action: 'none' },
		'PHP Compression':       { tip: i18n.tipPhpCompression || 'Enable zlib.output_compression in php.ini for automatic PHP output compression.', action: 'none' },
		'Server Compression':    { tip: i18n.tipServerCompression || 'Add mod_deflate or mod_gzip directives to your .htaccess file for Apache servers.', action: 'none' },
		'TTFB (Time To First Byte)': { tip: i18n.tipTtfb || 'Improve Time To First Byte by enabling object cache, page cache, and using a CDN.', action: 'none' },
		'CDN Detection':         { tip: i18n.tipCdn || 'Use a CDN (Cloudflare, Fastly, AWS CloudFront) for faster global content delivery.', action: 'none' },
		'Post Revisions':        { tip: i18n.tipPostRevisions || 'Clean up post revisions using the Database Cleanup tool below.', action: 'database', actionLabel: i18n.actionCleanRevisions || 'Clean Revisions' },
		'Auto-Drafts':           { tip: i18n.tipAutoDrafts || 'Remove auto-drafts using the Database Cleanup tool below.', action: 'database', actionLabel: i18n.actionCleanDrafts || 'Clean Drafts' },
		'Trashed Posts':         { tip: i18n.tipTrashedPosts || 'Empty the trash to free up database space.', action: 'database', actionLabel: i18n.actionCleanTrash || 'Clean Trash' },
		'Spam Comments':         { tip: i18n.tipSpamComments || 'Delete spam comments to keep your database lean.', action: 'database', actionLabel: i18n.actionCleanSpam || 'Clean Spam' },
		'Trashed Comments':      { tip: i18n.tipTrashedComments || 'Empty trashed comments from the database.', action: 'database', actionLabel: i18n.actionCleanTrash || 'Clean Trash' },
		'Expired Transients':    { tip: i18n.tipExpiredTransients || 'Clean expired transients to remove stale cached data.', action: 'database', actionLabel: i18n.actionCleanTransients || 'Clean Transients' },
		'Autoloaded Options':    { tip: i18n.tipAutoloadedOptions || 'Review autoloaded options. Plugins with large autoloaded data slow down every page load.', action: 'none' },
	};

	// ── DB cleanup type mapping ─────────────────────────────────────
	var DB_CLEANUP_TYPES = {
		revisions:           { label: i18n.labelPostRevisions || 'Post Revisions',           icon: 'fa-clock-rotate-left', type: 'revisions',           confirm: i18n.confirmRevisions || 'Delete all post revisions? This cannot be undone.' },
		auto_drafts:         { label: i18n.labelAutoDrafts || 'Auto-Drafts',                 icon: 'fa-file-pen',          type: 'auto_drafts',         confirm: i18n.confirmAutoDrafts || 'Delete all auto-drafts? This cannot be undone.' },
		trashed_posts:       { label: i18n.labelTrashedPosts || 'Trashed Posts',              icon: 'fa-trash-can',         type: 'trashed_posts',       confirm: i18n.confirmTrashedPosts || 'Permanently delete all trashed posts? This cannot be undone.' },
		spam_comments:       { label: i18n.labelSpamComments || 'Spam Comments',              icon: 'fa-ban',               type: 'spam_comments',       confirm: i18n.confirmSpamComments || 'Delete all spam comments? This cannot be undone.' },
		trashed_comments:    { label: i18n.labelTrashedComments || 'Trashed Comments',        icon: 'fa-comment-slash',     type: 'trashed_comments',    confirm: i18n.confirmTrashedComments || 'Permanently delete all trashed comments? This cannot be undone.' },
		expired_transients:  { label: i18n.labelExpiredTransients || 'Expired Transients',    icon: 'fa-hourglass-end',     type: 'expired_transients',  confirm: i18n.confirmExpiredTransients || 'Clean up all expired transients?' },
		optimize_tables:     { label: i18n.labelOptimizeTables || 'Optimize Tables',          icon: 'fa-wrench',            type: 'optimize_tables',     confirm: i18n.confirmOptimizeTables || 'Optimize all WordPress database tables? This is safe but may take a moment.' },
	};

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

	function createEl( tag, text, classes ) {
		var el = document.createElement( tag );
		if ( text ) {
			el.textContent = text;
		}
		if ( classes ) {
			el.className = classes;
		}
		return el;
	}

	function setLoading( btn, loading ) {
		if ( loading ) {
			btn._origNodes = Array.from( btn.childNodes ).map( function ( n ) { return n.cloneNode( true ); } );
			while ( btn.firstChild ) { btn.removeChild( btn.firstChild ); }
			var spinner = document.createElement( 'i' );
			spinner.className = 'fa-duotone fa-spinner-third fa-spin';
			btn.appendChild( spinner );
			btn.appendChild( document.createTextNode( ' ' + ( btn.dataset.loadingText || i18n.scanning || 'Scanning...' ) ) );
			btn.disabled = true;
			btn.classList.add( 'mc-btn-loading' );
		} else {
			while ( btn.firstChild ) { btn.removeChild( btn.firstChild ); }
			if ( btn._origNodes ) {
				btn._origNodes.forEach( function ( n ) { btn.appendChild( n ); } );
				delete btn._origNodes;
			}
			btn.disabled = false;
			btn.classList.remove( 'mc-btn-loading' );
		}
	}

	function scoreClass( score ) {
		if ( score >= 80 ) { return 'good'; }
		if ( score >= 50 ) { return 'ok'; }
		return 'bad';
	}

	function scoreMessage( score ) {
		if ( score >= 90 ) { return i18n.scoreExcellent || 'Excellent! Your site is well-optimized for speed. This is the Monitor.Cat Speed Score, not a Lighthouse score.'; }
		if ( score >= 80 ) { return i18n.scoreGreat || 'Great performance! A few tweaks below can push you even higher.'; }
		if ( score >= 60 ) { return i18n.scoreGood || 'Good foundation, but there are important speed improvements to make.'; }
		if ( score >= 40 ) { return i18n.scoreNeedsAttention || 'Your site needs attention. Follow the recommendations below to speed things up.'; }
		return i18n.scoreSignificant || 'Significant improvements needed. Start with the items marked "Fix This" below.';
	}

	function getFixUrl( action ) {
		if ( 'optimizations' === action ) {
			// Scroll to optimizations banner.
			var banner = document.getElementById( 'mc-speed-optimizations' );
			if ( banner ) {
				banner.scrollIntoView( { behavior: 'smooth', block: 'center' } );
			}
			return '';
		}
		if ( 'database' === action ) {
			// Switch to database tab.
			var dbTab = document.querySelector( '[data-tab-target="database"]' );
			if ( dbTab ) {
				dbTab.click();
				setTimeout( function () {
					var cleanup = document.querySelector( '.mc-db-cleanup-section' );
					if ( cleanup ) {
						cleanup.scrollIntoView( { behavior: 'smooth', block: 'center' } );
					}
				}, 200 );
			}
			return '';
		}
		return '';
	}

	// ── Score Ring Animation ─────────────────────────────────────────

	function animateScoreRing( score ) {
		var ring = document.getElementById( 'mc-speed-score-ring' );
		var numberEl = document.getElementById( 'mc-speed-score-number' );
		if ( ! ring ) { return; }

		var fill = ring.querySelector( '.mc-ring-fill' );
		var circumference = 2 * Math.PI * 52;
		var offset = circumference - ( ( score / 100 ) * circumference );

		ring.className = 'mc-score-ring mc-ring-' + scoreClass( score );

		requestAnimationFrame( function () {
			fill.style.strokeDashoffset = String( offset );
		} );

		var current = 0;
		var step = Math.max( 1, Math.ceil( score / 40 ) );
		var timer = setInterval( function () {
			current += step;
			if ( current >= score ) {
				current = score;
				clearInterval( timer );
			}
			if ( numberEl ) {
				numberEl.textContent = String( current );
			}
		}, 25 );
	}

	// ── Render Functions ─────────────────────────────────────────────

	function renderHeroBadges( analyzers ) {
		var container = document.getElementById( 'mc-speed-hero-badges' );
		if ( ! container ) { return; }
		while ( container.firstChild ) { container.removeChild( container.firstChild ); }

		var counts = { good: 0, warning: 0, critical: 0 };
		Object.keys( analyzers ).forEach( function ( key ) {
			var status = analyzers[ key ].status;
			counts[ status ] = ( counts[ status ] || 0 ) + 1;
		} );

		if ( counts.good > 0 ) {
			container.appendChild( createEl( 'span', counts.good + ' ' + ( i18n.badgePassing || 'Passing' ), 'mc-badge mc-badge-success mc-badge-dot' ) );
		}
		if ( counts.warning > 0 ) {
			container.appendChild( createEl( 'span', counts.warning + ' ' + ( i18n.badgeNeedsWork || 'Needs Work' ), 'mc-badge mc-badge-warning mc-badge-dot' ) );
		}
		if ( counts.critical > 0 ) {
			container.appendChild( createEl( 'span', counts.critical + ' ' + ( i18n.badgeFixThis || 'Fix This' ), 'mc-badge mc-badge-error mc-badge-dot' ) );
		}
	}

	function renderOptimizations( optimizations ) {
		var wrapper = document.getElementById( 'mc-speed-optimizations' );
		var grid = document.getElementById( 'mc-speed-optimizations-grid' );
		var countBadge = document.getElementById( 'mc-speed-opt-count' );
		if ( ! wrapper || ! grid ) { return; }

		while ( grid.firstChild ) { grid.removeChild( grid.firstChild ); }

		if ( ! Array.isArray( optimizations ) || optimizations.length === 0 ) {
			wrapper.style.display = 'none';
			return;
		}

		var activeCount = optimizations.filter( function ( o ) { return o.active; } ).length;
		if ( countBadge ) {
			countBadge.textContent = ( i18n.activeOf || '%1$d of %2$d active' ).replace( '%1$d', activeCount ).replace( '%2$d', optimizations.length );
		}

		optimizations.forEach( function ( opt ) {
			var item = createEl( 'div', null, 'mc-speed-opt-item' + ( opt.active ? ' is-active' : '' ) );

			var iconWrap = createEl( 'div', null, 'mc-pedestal mc-pedestal-xs mc-pedestal-' + opt.color );
			var icon = createEl( 'i', null, 'fa-duotone ' + opt.icon + ' mc-fa-' + opt.color );
			iconWrap.appendChild( icon );
			item.appendChild( iconWrap );

			var info = createEl( 'div', null, 'mc-speed-opt-info' );
			info.appendChild( createEl( 'div', opt.label, 'mc-speed-opt-label' ) );
			info.appendChild( createEl( 'div', opt.detail || '', 'mc-speed-opt-detail' ) );
			item.appendChild( info );

			// Toggle switch.
			var toggle = document.createElement( 'label' );
			toggle.className = 'mc-toggle';
			var input = document.createElement( 'input' );
			input.type = 'checkbox';
			input.checked = opt.active;
			input.dataset.key = opt.key;
			var slider = createEl( 'span', null, 'mc-toggle-slider' );
			toggle.appendChild( input );
			toggle.appendChild( slider );
			item.appendChild( toggle );

			// Handle toggle change.
			input.addEventListener( 'change', function () {
				var body = {};
				body[ opt.key ] = input.checked;
				item.classList.toggle( 'is-active', input.checked );

				api.apiFetch( '/speed/settings', {
					method: 'POST',
					body: JSON.stringify( body ),
				} )
					.then( function () {
						var msg = input.checked
						? ( i18n.enabledNotice || '%s enabled. Takes effect on next page load.' ).replace( '%s', opt.label )
						: ( i18n.disabledNotice || '%s disabled. Takes effect on next page load.' ).replace( '%s', opt.label );
					api.notify( msg, 'success' );
						// Update count.
						var allChecked = grid.querySelectorAll( 'input[type="checkbox"]:checked' ).length;
						var allInputs = grid.querySelectorAll( 'input[type="checkbox"]' ).length;
						if ( countBadge ) {
							countBadge.textContent = allChecked + ' of ' + allInputs + ' active';
						}
					} )
					.catch( function () {
						input.checked = ! input.checked;
						item.classList.toggle( 'is-active', input.checked );
						api.notify( i18n.failedSaveSetting || 'Failed to save setting.', 'error' );
					} );
			} );

			grid.appendChild( item );
		} );

		wrapper.style.display = '';
	}

	function renderCategoryCard( key, analyzerData, meta ) {
		var card = createEl( 'div', null, 'mc-card mc-speed-check-card mc-speed-check-' + analyzerData.status );

		// Header.
		var header = createEl( 'div', null, 'mc-speed-check-header' );
		var pedestal = createEl( 'div', null, 'mc-pedestal mc-pedestal-sm mc-pedestal-' + meta.color );
		var icon = createEl( 'i', null, 'fa-duotone ' + meta.icon + ' mc-fa-' + meta.color );
		pedestal.appendChild( icon );
		header.appendChild( pedestal );

		var headerInfo = createEl( 'div', null, 'mc-speed-check-header-info' );
		headerInfo.appendChild( createEl( 'h3', meta.label, 'mc-heading-sm' ) );
		var statusBadge = createEl( 'span', STATUS_LABELS[ analyzerData.status ] || analyzerData.status, 'mc-badge mc-badge-' + ( STATUS_BADGE[ analyzerData.status ] || 'neutral' ) );
		headerInfo.appendChild( statusBadge );
		header.appendChild( headerInfo );

		var scoreText = createEl( 'div', analyzerData.score + '/100', 'mc-speed-check-score mc-text-' + scoreClass( analyzerData.score ) );
		header.appendChild( scoreText );
		card.appendChild( header );

		// Progress bar.
		var progressWrap = createEl( 'div', null, 'mc-progress-bar mc-speed-check-progress' );
		var progressFill = createEl( 'div', null, 'mc-progress-bar-fill' );
		progressFill.style.width = analyzerData.score + '%';
		progressWrap.className += ' mc-progress-' + scoreClass( analyzerData.score );
		progressWrap.appendChild( progressFill );
		card.appendChild( progressWrap );

		// Checks list.
		if ( analyzerData.checks && analyzerData.checks.length > 0 ) {
			var list = createEl( 'ul', null, 'mc-speed-checklist' );

			analyzerData.checks.forEach( function ( check ) {
				var li = createEl( 'li', null, 'mc-speed-check-item' );
				var fixData = check.status !== 'good' ? ( FIX_TIPS[ check.label ] || null ) : null;

				if ( fixData ) {
					li.classList.add( 'is-fixable' );
				}

				var iconCircle = createEl( 'div', null, 'mc-speed-check-icon is-' + ( check.status === 'warning' ? 'warn' : check.status ) );
				var statusIcon = createEl( 'i', null, 'fa-duotone ' + ( STATUS_ICON[ check.status ] || 'fa-circle' ) );
				iconCircle.appendChild( statusIcon );
				li.appendChild( iconCircle );

				var content = createEl( 'div', null, 'mc-speed-check-content' );
				content.appendChild( createEl( 'div', check.label || '', 'mc-speed-check-title' ) );
				content.appendChild( createEl( 'div', check.message || '', 'mc-speed-check-desc' ) );
				if ( check.value ) {
					content.appendChild( createEl( 'div', check.value, 'mc-speed-check-value' ) );
				}

				// Fix panel.
				if ( fixData ) {
					var fixPanel = createEl( 'div', null, 'mc-speed-fix-panel' );
					var fixRow = createEl( 'div', null, 'mc-speed-fix-row' );
					var fixIcon = createEl( 'i', null, 'fa-duotone fa-lightbulb mc-fa-primary' );
					var fixTip = createEl( 'span', fixData.tip, 'mc-speed-fix-tip' );
					fixRow.appendChild( fixIcon );
					fixRow.appendChild( fixTip );
					fixPanel.appendChild( fixRow );

					if ( fixData.action !== 'none' && fixData.actionLabel ) {
						var fixBtn = document.createElement( 'button' );
						fixBtn.type = 'button';
						fixBtn.className = 'mc-btn mc-btn-xs mc-btn-primary mc-speed-fix-btn';
						fixBtn.textContent = fixData.actionLabel;
						var btnAction = fixData.action;
						fixBtn.addEventListener( 'click', function ( e ) {
							e.stopPropagation();
							getFixUrl( btnAction );
						} );
						fixPanel.appendChild( fixBtn );
					}

					content.appendChild( fixPanel );
				}

				li.appendChild( content );

				// Chevron.
				if ( fixData ) {
					var chevron = createEl( 'div', null, 'mc-speed-check-chevron' );
					chevron.appendChild( createEl( 'i', null, 'fa-duotone fa-chevron-down' ) );
					li.appendChild( chevron );

					li.addEventListener( 'click', ( function ( item ) {
						return function ( e ) {
							if ( e.target.closest( '.mc-speed-fix-btn' ) ) { return; }
							item.classList.toggle( 'is-expanded' );
						};
					} )( li ) );
				}

				list.appendChild( li );
			} );

			card.appendChild( list );
		}

		return card;
	}

	function renderCategory( gridId, categoryMap, analyzers ) {
		var grid = document.getElementById( gridId );
		if ( ! grid ) { return; }
		while ( grid.firstChild ) { grid.removeChild( grid.firstChild ); }

		var priority = { critical: 0, warning: 1, good: 2 };
		var items = [];
		Object.keys( categoryMap ).forEach( function ( key ) {
			if ( analyzers[ key ] ) {
				items.push( { key: key, data: analyzers[ key ], meta: categoryMap[ key ] } );
			}
		} );

		items.sort( function ( a, b ) {
			return ( priority[ a.data.status ] || 2 ) - ( priority[ b.data.status ] || 2 );
		} );

		if ( items.length === 0 ) {
			grid.appendChild( createEl( 'p', i18n.noDataAvailable || 'No data available for this category.', 'mc-text-medium' ) );
			return;
		}

		// Summary bar.
		var passing = items.filter( function ( i ) { return i.data.status === 'good'; } ).length;
		var summary = createEl( 'div', null, 'mc-speed-tab-summary' );
		var avgScore = Math.round( items.reduce( function ( sum, i ) { return sum + i.data.score; }, 0 ) / items.length );
		summary.appendChild( createEl( 'span', ( i18n.checksPassingOf || '%1$d of %2$d checks passing' ).replace( '%1$d', passing ).replace( '%2$d', items.length ), 'mc-text-medium' ) );
		var summaryBadge = createEl( 'span', ( i18n.avgScore || '%d/100 avg' ).replace( '%d', avgScore ), 'mc-badge mc-badge-' + ( STATUS_BADGE[ avgScore >= 80 ? 'good' : ( avgScore >= 50 ? 'warning' : 'critical' ) ] ) );
		summary.appendChild( summaryBadge );
		grid.appendChild( summary );

		// Cards.
		items.forEach( function ( item ) {
			var card = renderCategoryCard( item.key, item.data, item.meta );

			if ( item.data.status === 'good' ) {
				card.classList.add( 'is-collapsible', 'is-collapsed' );
				var toggleBtn = document.createElement( 'button' );
				toggleBtn.type = 'button';
				toggleBtn.className = 'mc-speed-collapse-toggle';
				var toggleText = document.createElement( 'span' );
				toggleText.textContent = i18n.details || 'Details';
				var toggleIcon = document.createElement( 'i' );
				toggleIcon.className = 'fa-duotone fa-chevron-up';
				toggleBtn.appendChild( toggleText );
				toggleBtn.appendChild( toggleIcon );
				card.appendChild( toggleBtn );

				card.addEventListener( 'click', function () {
					card.classList.toggle( 'is-collapsed' );
				} );
			}

			grid.appendChild( card );
		} );
	}

	function updateTabLabel( tabName, categoryMap, analyzers ) {
		var tabBtn = document.querySelector( '[data-tab-target="' + tabName + '"]' );
		if ( ! tabBtn ) { return; }

		var issues = 0;
		var total = 0;
		Object.keys( categoryMap ).forEach( function ( key ) {
			if ( analyzers[ key ] ) {
				total++;
				if ( analyzers[ key ].status !== 'good' ) {
					issues++;
				}
			}
		} );

		var labels = {
			performance: i18n.tabPerformance || 'Performance',
			infrastructure: i18n.tabInfrastructure || 'Infrastructure',
			database: i18n.tabDatabase || 'Database',
		};
		var label = labels[ tabName ] || tabName;

		if ( issues > 0 ) {
			while ( tabBtn.firstChild ) { tabBtn.removeChild( tabBtn.firstChild ); }
			tabBtn.appendChild( document.createTextNode( label + ' ' ) );
			var badge = createEl( 'span', String( issues ), 'mc-tab-count mc-tab-count-' + ( issues >= total ? 'error' : 'warning' ) );
			tabBtn.appendChild( badge );
		} else {
			tabBtn.textContent = label + ' \u2713';
		}
	}

	// ── DB Stats & Cleanup ───────────────────────────────────────────

	function loadDbStats() {
		var container = document.getElementById( 'mc-db-stats' );
		if ( ! container ) { return; }

		api.apiFetch( '/speed/db-stats', { method: 'GET' } )
			.then( function ( response ) {
				var stats = response.data || response;
				renderDbStats( stats, container );
			} )
			.catch( function () {
				container.appendChild( createEl( 'p', i18n.failedLoadDbStats || 'Failed to load database stats.', 'mc-text-medium' ) );
			} );
	}

	function renderDbStats( stats, container ) {
		while ( container.firstChild ) { container.removeChild( container.firstChild ); }

		var statKeys = Object.keys( DB_CLEANUP_TYPES );
		statKeys.forEach( function ( key ) {
			var meta = DB_CLEANUP_TYPES[ key ];
			var count = stats[ key ] || 0;
			var isOptimize = key === 'optimize_tables';

			var card = createEl( 'div', null, 'mc-db-stat-card' + ( ! isOptimize && count > 0 ? ' has-items' : '' ) );

			var cardTop = createEl( 'div', null, 'mc-db-stat-top' );
			var iconEl = createEl( 'i', null, 'fa-duotone ' + meta.icon + ' mc-fa-cyan' );
			cardTop.appendChild( iconEl );
			cardTop.appendChild( createEl( 'span', isOptimize ? '' : String( count ), 'mc-db-stat-count' ) );
			card.appendChild( cardTop );

			card.appendChild( createEl( 'div', meta.label, 'mc-db-stat-label' ) );

			var btn = document.createElement( 'button' );
			btn.type = 'button';
			btn.className = 'mc-btn mc-btn-xs mc-btn-secondary mc-db-cleanup-btn';
			btn.dataset.cleanupType = meta.type;
			btn.dataset.loadingText = i18n.cleaning || 'Cleaning...';
			btn.textContent = isOptimize ? ( i18n.optimize || 'Optimize' ) : ( i18n.clean || 'Clean' );

			if ( ! isOptimize && count === 0 ) {
				btn.disabled = true;
			}

			btn.addEventListener( 'click', function ( e ) {
				e.stopPropagation();
				handleCleanup( btn, meta, card );
			} );

			card.appendChild( btn );
			container.appendChild( card );
		} );
	}

	function handleCleanup( btn, meta, card ) {
		if ( ! window.confirm( meta.confirm ) ) { // eslint-disable-line no-alert
			return;
		}

		setLoading( btn, true );

		api.apiFetch( '/speed/db-cleanup', {
			method: 'POST',
			body: JSON.stringify( { type: meta.type } ),
		} )
			.then( function ( response ) {
				setLoading( btn, false );
				var data = response.data || response;
				var count = data.count || 0;
				api.notify( data.message || ( i18n.cleanedItems || 'Cleaned %d items.' ).replace( '%d', count ), 'success' );

				// Update the stat count on the card.
				var countEl = card.querySelector( '.mc-db-stat-count' );
				if ( countEl ) {
					countEl.textContent = '0';
				}
				card.classList.remove( 'has-items' );
				btn.disabled = true;
			} )
			.catch( function ( err ) {
				setLoading( btn, false );
				api.notify( err.message || ( i18n.cleanupFailed || 'Cleanup failed.' ), 'error' );
			} );
	}

	function handleCleanAll() {
		if ( ! window.confirm( i18n.confirmCleanAll || 'Run all database cleanups? This will remove revisions, drafts, trash, spam, and expired transients. This cannot be undone.' ) ) { // eslint-disable-line no-alert
			return;
		}

		var btn = document.getElementById( 'mc-db-clean-all-btn' );
		if ( btn ) { setLoading( btn, true ); }

		var types = [ 'revisions', 'auto_drafts', 'trashed_posts', 'spam_comments', 'trashed_comments', 'expired_transients', 'optimize_tables' ];
		var completed = 0;
		var totalCleaned = 0;

		types.forEach( function ( type ) {
			api.apiFetch( '/speed/db-cleanup', {
				method: 'POST',
				body: JSON.stringify( { type: type } ),
			} )
				.then( function ( response ) {
					var data = response.data || response;
					totalCleaned += data.count || 0;
				} )
				.finally( function () {
					completed++;
					if ( completed === types.length ) {
						if ( btn ) { setLoading( btn, false ); }
						api.notify( ( i18n.allCleanupsComplete || 'All cleanups complete! Cleaned %d items and optimized tables.' ).replace( '%d', totalCleaned ), 'success' );
						loadDbStats();
					}
				} );
		} );
	}

	// ── Loading Step Animation ────────────────────────────────────────

	var loadingTimer = null;

	function startLoadingSteps() {
		var steps = document.querySelectorAll( '.mc-speed-loading-step' );
		if ( ! steps.length ) { return; }

		var index = 0;
		steps[ 0 ].classList.add( 'is-active' );
		var firstIcon = steps[ 0 ].querySelector( 'i' );
		if ( firstIcon ) { firstIcon.className = 'fa-duotone fa-spinner-third fa-spin'; }

		loadingTimer = setInterval( function () {
			if ( steps[ index ] ) {
				steps[ index ].classList.remove( 'is-active' );
				steps[ index ].classList.add( 'is-done' );
				var doneIcon = steps[ index ].querySelector( 'i' );
				if ( doneIcon ) { doneIcon.className = 'fa-duotone fa-circle-check'; }
			}
			index++;
			if ( index < steps.length ) {
				steps[ index ].classList.add( 'is-active' );
				var activeIcon = steps[ index ].querySelector( 'i' );
				if ( activeIcon ) { activeIcon.className = 'fa-duotone fa-spinner-third fa-spin'; }
			} else {
				clearInterval( loadingTimer );
				loadingTimer = null;
			}
		}, 800 );
	}

	function stopLoadingSteps() {
		if ( loadingTimer ) {
			clearInterval( loadingTimer );
			loadingTimer = null;
		}
		var steps = document.querySelectorAll( '.mc-speed-loading-step' );
		steps.forEach( function ( step ) {
			step.classList.remove( 'is-active' );
			step.classList.add( 'is-done' );
			var icon = step.querySelector( 'i' );
			if ( icon ) { icon.className = 'fa-duotone fa-circle-check'; }
		} );
	}

	function resetLoadingSteps() {
		var steps = document.querySelectorAll( '.mc-speed-loading-step' );
		steps.forEach( function ( step ) {
			step.classList.remove( 'is-active', 'is-done' );
			var icon = step.querySelector( 'i' );
			if ( icon ) { icon.className = 'fa-duotone fa-ellipsis'; }
		} );
	}

	// ── Render Results ───────────────────────────────────────────────

	function renderResults( data ) {
		var loadingEl = document.getElementById( 'mc-speed-loading' );
		var resultsEl = document.getElementById( 'mc-speed-results' );
		var emptyEl = document.getElementById( 'mc-speed-empty' );

		if ( loadingEl ) { loadingEl.style.display = 'none'; }
		if ( emptyEl ) { emptyEl.style.display = 'none'; }
		if ( resultsEl ) { resultsEl.style.display = ''; }

		var result = data.data || data;
		var score = result.overall_score !== undefined ? result.overall_score : 0;
		var analyzers = result.analyzers || {};

		// Hero.
		animateScoreRing( score );

		var desc = document.getElementById( 'mc-speed-hero-desc' );
		if ( desc ) { desc.textContent = scoreMessage( score ); }

		renderHeroBadges( analyzers );

		// Lighthouse external link — build PageSpeed Insights URL with site URL.
		var lighthouseLink = document.getElementById( 'mc-lighthouse-link' );
		if ( lighthouseLink ) {
			var siteUrl = ( window.MonitorCat && window.MonitorCat.siteUrl ) || '';
			if ( siteUrl ) {
				lighthouseLink.href = 'https://pagespeed.web.dev/analysis?url=' + encodeURIComponent( siteUrl );
			}
		}

		// Optimizations banner.
		renderOptimizations( result.optimizations );

		// Tabs.
		renderCategory( 'mc-speed-perf-grid', CATEGORIES.performance, analyzers );
		renderCategory( 'mc-speed-infra-grid', CATEGORIES.infrastructure, analyzers );
		renderCategory( 'mc-speed-db-grid', CATEGORIES.database, analyzers );

		updateTabLabel( 'performance', CATEGORIES.performance, analyzers );
		updateTabLabel( 'infrastructure', CATEGORIES.infrastructure, analyzers );
		updateTabLabel( 'database', CATEGORIES.database, analyzers );

		// Re-init tabs.
		var tabContainer = document.querySelector( '.mc-speed-tabs' );
		if ( tabContainer && api.initTabs ) {
			api.initTabs( tabContainer );
		}

		// Load DB stats for cleanup section.
		loadDbStats();
	}

	// ── Scan ─────────────────────────────────────────────────────────

	function runScan() {
		var loadingEl = document.getElementById( 'mc-speed-loading' );
		var resultsEl = document.getElementById( 'mc-speed-results' );
		var emptyEl = document.getElementById( 'mc-speed-empty' );
		var btn = document.getElementById( 'mc-speed-scan-btn' );

		if ( loadingEl ) { loadingEl.style.display = ''; }
		if ( resultsEl ) { resultsEl.style.display = 'none'; }
		if ( emptyEl ) { emptyEl.style.display = 'none'; }
		if ( btn ) { setLoading( btn, true ); }

		resetLoadingSteps();
		startLoadingSteps();

		api.apiFetch( '/speed/scan', { method: 'POST' } )
			.then( function ( data ) {
				stopLoadingSteps();
				setTimeout( function () {
					if ( btn ) { setLoading( btn, false ); }
					renderResults( data );
					api.notify( i18n.scanComplete || 'Speed scan complete!', 'success' );
				}, 400 );
			} )
			.catch( function ( err ) {
				stopLoadingSteps();
				if ( btn ) { setLoading( btn, false ); }
				if ( loadingEl ) { loadingEl.style.display = 'none'; }
				if ( emptyEl ) { emptyEl.style.display = ''; }
				api.notify( err.message || ( i18n.scanFailed || 'Scan failed. Please try again.' ), 'error' );
			} );
	}

	// ── Init ─────────────────────────────────────────────────────────

	document.addEventListener( 'DOMContentLoaded', function () {
		var page = document.querySelector( '.mc-speed-page' );
		if ( ! page ) { return; }

		// Auto-scan on load.
		runScan();

		// Rescan button.
		var scanBtn = document.getElementById( 'mc-speed-scan-btn' );
		if ( scanBtn ) {
			scanBtn.addEventListener( 'click', function () {
				try { runScan(); } catch ( err ) {
					api.notify( 'An unexpected error occurred.', 'error' );
				}
			} );
		}

		// Clean All button.
		var cleanAllBtn = document.getElementById( 'mc-db-clean-all-btn' );
		if ( cleanAllBtn ) {
			cleanAllBtn.addEventListener( 'click', function () {
				try { handleCleanAll(); } catch ( err ) {
					api.notify( 'An unexpected error occurred.', 'error' );
				}
			} );
		}
	} );
} )();
