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

/**
 * Monitor.Cat — SEO & GEO module.
 *
 * Two-section layout:
 * 1. Site Health — loads immediately with site-wide checks
 * 2. Page Analysis — per-page checks with page picker
 *
 * @package MonitorCat
 */
( function () {
	'use strict';

	var api = window.MonitorCatAdmin;

	// ── Constants ────────────────────────────────────────────────────

	var SITE_CATEGORIES = {
		sitemap:    { icon: 'fa-sitemap',        color: 'mint',    label: 'XML Sitemap' },
		robots:     { icon: 'fa-shield-halved',  color: 'coral',   label: 'Robots.txt' },
		ai_crawler: { icon: 'fa-spider-web',     color: 'cyan',    label: 'AI Crawler Access' },
		llms_txt:   { icon: 'fa-file-lines',     color: 'mint',    label: 'llms.txt' },
	};

	var PAGE_CATEGORIES = {
		meta:          { icon: 'fa-tag',                color: 'primary',  label: 'Meta Tags' },
		open_graph:    { icon: 'fa-share-nodes',        color: 'lavender', label: 'Social Sharing' },
		headings:      { icon: 'fa-heading',            color: 'cyan',     label: 'Heading Structure' },
		images:        { icon: 'fa-image',              color: 'mint',     label: 'Image Alt Text' },
		links:         { icon: 'fa-link',               color: 'pink',     label: 'Link Analysis' },
		readability:   { icon: 'fa-book-open',          color: 'lavender', label: 'Readability' },
		schema:        { icon: 'fa-code',               color: 'cyan',     label: 'Structured Data' },
		canonical:     { icon: 'fa-link-horizontal',    color: 'primary',  label: 'Canonical URLs' },
		geo_readiness: { icon: 'fa-robot',              color: 'lavender', label: 'AI Readiness' },
	};

	var STATUS_LABELS = {
		pass:    'Passing',
		warning: 'Needs Work',
		fail:    'Fix This',
	};

	var STATUS_BADGE = {
		pass:    'success',
		warning: 'warning',
		fail:    'error',
	};

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

	// ── Fix tips per check label ────────────────────────────────────
	var FIX_TIPS = {
		// MetaAnalyzer labels.
		'Post Title':          { tip: 'Add a descriptive, keyword-rich title in the WordPress editor.', action: 'edit_post', actionLabel: 'Edit Post' },
		'Title Length':        { tip: 'Aim for 50\u201360 characters. Keep it descriptive but concise to avoid truncation in search results.', action: 'edit_post', actionLabel: 'Edit Post' },
		'Meta Description':    { tip: 'Add a post excerpt or enable Monitor.Cat auto meta tags to generate one automatically.', action: 'edit_post', actionLabel: 'Edit Post' },
		'Description Length':  { tip: 'Aim for 150\u2013160 characters. Summarize the page content in a way that compels clicks.', action: 'edit_post', actionLabel: 'Edit Post' },
		'Duplicate Title':     { tip: 'Make each page title unique so your pages don\u2019t compete with each other in search results.', action: 'edit_post', actionLabel: 'Edit Post' },

		// OpenGraphAnalyzer labels.
		'SEO Plugin':          { tip: 'Enable Monitor.Cat auto meta tags in SEO settings, or install a dedicated SEO plugin.', action: 'settings', actionLabel: 'SEO Settings' },
		'OG Title':            { tip: 'Set an Open Graph title via your SEO plugin, or enable Monitor.Cat auto meta tags.', action: 'settings', actionLabel: 'SEO Settings' },
		'OG Description':      { tip: 'Set an OG description via your SEO plugin, or add a post excerpt as fallback.', action: 'edit_post', actionLabel: 'Edit Post' },
		'OG Image':            { tip: 'Set a featured image on the post. Recommended size: 1200\u00d7630px for best social sharing.', action: 'edit_post', actionLabel: 'Set Featured Image' },

		// HeadingAnalyzer labels.
		'H1 Usage':            { tip: 'Ensure your content has exactly one H1 tag. WordPress themes usually render the post title as H1.', action: 'edit_post', actionLabel: 'Edit Post' },
		'Heading Hierarchy':   { tip: 'Use headings in order (H1 \u2192 H2 \u2192 H3). Don\u2019t skip levels.', action: 'edit_post', actionLabel: 'Edit Post' },
		'H2 Subheadings':      { tip: 'Break up long content with H2 subheadings every 300\u2013400 words.', action: 'edit_post', actionLabel: 'Edit Post' },
		'Heading Density':     { tip: 'Add more subheadings to break up long text sections and improve scanability.', action: 'edit_post', actionLabel: 'Edit Post' },
		'Heading Structure':   { tip: 'Use descriptive headings that preview the content of each section.', action: 'edit_post', actionLabel: 'Edit Post' },

		// ImageAltAnalyzer labels.
		'Image Alt Coverage':  { tip: 'Add descriptive alt text to all images. This helps SEO and accessibility.', action: 'edit_post', actionLabel: 'Edit Post' },
		'Missing Alt Text':    { tip: 'Write meaningful alt text that describes the image content. Avoid generic text like "image" or "photo".', action: 'edit_post', actionLabel: 'Edit Post' },
		'Featured Image Alt':  { tip: 'Set alt text on your featured image for better social sharing and accessibility.', action: 'edit_post', actionLabel: 'Edit Post' },

		// LinkAnalyzer labels.
		'Link Count':          { tip: 'Add relevant links to improve content discoverability and authority.', action: 'edit_post', actionLabel: 'Edit Post' },
		'Internal Links':      { tip: 'Link to other relevant pages on your site to help search engines discover your content.', action: 'edit_post', actionLabel: 'Edit Post' },
		'External Links':      { tip: 'Link to authoritative external sources to add credibility and context.', action: 'edit_post', actionLabel: 'Edit Post' },
		'Broken Links':        { tip: 'Fix or remove broken links to improve user experience and SEO.', action: 'edit_post', actionLabel: 'Edit Post' },

		// ReadabilityAnalyzer labels.
		'Readability Score':   { tip: 'Simplify complex sentences. Use shorter paragraphs and common words.', action: 'edit_post', actionLabel: 'Edit Post' },
		'Paragraph Structure': { tip: 'Break up walls of text into shorter paragraphs for better readability.', action: 'edit_post', actionLabel: 'Edit Post' },
		'Sentence Length':     { tip: 'Aim for an average of 15\u201320 words per sentence. Mix short and long sentences.', action: 'edit_post', actionLabel: 'Edit Post' },
		'Word Count':          { tip: 'Aim for at least 300 words. Longer, in-depth content tends to rank better.', action: 'edit_post', actionLabel: 'Edit Post' },

		// SchemaAnalyzer labels.
		'SEO Plugin Schema':   { tip: 'Enable Monitor.Cat JSON-LD Schema in SEO settings for automatic structured data.', action: 'settings', actionLabel: 'SEO Settings' },
		'Schema Plugin':       { tip: 'A dedicated schema plugin can add product, recipe, or event markup beyond basic types.', action: 'none' },
		'Inline JSON-LD':      { tip: 'This is informational. JSON-LD is typically output by plugins, not inline in content.', action: 'none' },

		// CanonicalAnalyzer labels.
		'WordPress Canonical': { tip: 'Enable Monitor.Cat canonical URLs or use an SEO plugin to set them.', action: 'settings', actionLabel: 'SEO Settings' },
		'Canonical Override':  { tip: 'Set a custom canonical URL if this content appears on multiple URLs.', action: 'edit_post', actionLabel: 'Edit Post' },
		'HTTPS Consistency':   { tip: 'Ensure your site uses HTTPS consistently. Update Site URL in Settings \u2192 General.', action: 'none' },
		'Permalink Structure': { tip: 'Use SEO-friendly permalinks. Go to Settings \u2192 Permalinks and choose "Post name".', action: 'none' },

		// SitemapAnalyzer labels.
		'WordPress Sitemap':   { tip: 'Ensure an XML sitemap exists. WordPress 5.5+ generates one automatically at /wp-sitemap.xml.', action: 'none' },
		'Yoast Sitemap':       { tip: 'Yoast SEO provides an enhanced sitemap. Check your sitemap settings in the SEO plugin.', action: 'none' },
		'Robots.txt Sitemap':  { tip: 'Your sitemap URL should be referenced in robots.txt for search engine discovery.', action: 'none' },

		// RobotsAnalyzer labels.
		'Search Engine Visibility': { tip: 'Your site may be set to discourage search engines. Check Settings \u2192 Reading in WordPress.', action: 'none' },
		'Robots.txt File':     { tip: 'Ensure robots.txt exists and doesn\u2019t block important pages or your sitemap.', action: 'none' },
		'Restrictive Rules':   { tip: 'Review your robots.txt to ensure search engines can access your content.', action: 'none' },
		'Sitemap in Robots.txt': { tip: 'Add your sitemap URL to robots.txt so crawlers can find it automatically.', action: 'none' },

		// AiCrawlerAnalyzer labels.
		'GPTBot Access (ChatGPT)': { tip: 'GPTBot is currently blocked in robots.txt. Allow it if you want ChatGPT to reference your content.', action: 'none' },
		'ClaudeBot Access (Claude)': { tip: 'ClaudeBot is currently blocked in robots.txt. Allow it if you want Claude to reference your content.', action: 'none' },
		'Other AI Bots':       { tip: 'Some AI crawlers are blocked. Review your robots.txt to decide which AI bots should access your content.', action: 'none' },
		'Crawl Delay':         { tip: 'High crawl delays slow down AI indexing. Consider lowering or removing the crawl-delay directive.', action: 'none' },

		// LlmsTxtAnalyzer labels.
		'llms.txt Exists':     { tip: 'Enable the llms.txt generator in SEO settings to help AI models understand your site.', action: 'settings', actionLabel: 'SEO Settings' },
		'Content Format':      { tip: 'Your llms.txt should follow the standard Markdown format for best AI compatibility.', action: 'settings', actionLabel: 'SEO Settings' },
		'Content Coverage':    { tip: 'Ensure llms.txt covers your key pages and content areas.', action: 'settings', actionLabel: 'SEO Settings' },

		// GeoReadinessAnalyzer labels.
		'Content Structure':   { tip: 'Structure content with clear headings, factual claims, and cited sources so AI can extract answers.', action: 'edit_post', actionLabel: 'Edit Post' },
		'Q&A Headings':        { tip: 'Use question-format headings (How, What, Why) so AI can match user queries to your content.', action: 'edit_post', actionLabel: 'Edit Post' },
		'Definition Leads':    { tip: 'Start paragraphs with clear definitions or direct answers for better AI extraction.', action: 'edit_post', actionLabel: 'Edit Post' },
		'Data Density':        { tip: 'Include specific numbers, statistics, and data points that AI can cite as facts.', action: 'edit_post', actionLabel: 'Edit Post' },
		'Source Citations':    { tip: 'Include specific facts, statistics, and quotable statements that AI can cite.', action: 'edit_post', actionLabel: 'Edit Post' },
		'Entity Clarity':      { tip: 'Clearly define who/what your content is about in the first paragraph.', action: 'edit_post', actionLabel: 'Edit Post' },
		'Content Freshness':   { tip: 'Update your content regularly and include publication/modification dates.', action: 'edit_post', actionLabel: 'Edit Post' },
	};

	// ── State ────────────────────────────────────────────────────────
	var currentPostId = 0;
	var TOOLTIP_STORAGE_KEY = 'mc_seo_deeplink_tip_dismissed';

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

	function getFixUrl( action ) {
		var base = ( window.MonitorCat && window.MonitorCat.adminUrl ) || '/wp-admin/';
		if ( 'edit_post' === action && currentPostId ) {
			return base + 'post.php?post=' + currentPostId + '&action=edit';
		}
		if ( 'settings' === action ) {
			return base + 'admin.php?page=monitor-cat-seo';
		}
		return '';
	}

	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 || '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 'Fully optimized! Monitor.Cat is handling meta tags, schema, and social sharing for this page.'; }
		if ( score >= 80 ) { return 'Monitor.Cat is actively improving this page. A few manual tweaks below will push it even higher.'; }
		if ( score >= 60 ) { return 'Monitor.Cat is generating meta tags and schema for this page. Fix the items below to maximize visibility.'; }
		if ( score >= 40 ) { return 'Monitor.Cat is protecting basics, but this page needs your attention on the items below.'; }
		return 'This page needs work. Monitor.Cat is handling schema and meta, but review the recommendations below.';
	}

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

	function animateScoreRing( score ) {
		var ring = document.getElementById( 'mc-seo-score-ring' );
		var numberEl = document.getElementById( 'mc-seo-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-seo-hero-badges' );
		if ( ! container ) { return; }
		while ( container.firstChild ) { container.removeChild( container.firstChild ); }

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

		if ( counts.pass > 0 ) { container.appendChild( createEl( 'span', counts.pass + ' Passing', 'mc-badge mc-badge-success mc-badge-dot' ) ); }
		if ( counts.warning > 0 ) { container.appendChild( createEl( 'span', counts.warning + ' Needs Work', 'mc-badge mc-badge-warning mc-badge-dot' ) ); }
		if ( counts.fail > 0 ) { container.appendChild( createEl( 'span', counts.fail + ' Fix This', 'mc-badge mc-badge-error mc-badge-dot' ) ); }
	}

	function renderProtections( protections ) {
		var wrapper = document.getElementById( 'mc-seo-protections' );
		var container = document.getElementById( 'mc-seo-protections-items' );
		if ( ! wrapper || ! container ) { return; }

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

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

		protections.forEach( function ( p ) {
			var span = createEl( 'span', null, 'mc-seo-protection-item' );
			var icon = createEl( 'i', null, 'fa-duotone ' + p.icon + ' mc-fa-' + p.color );
			span.appendChild( icon );
			span.appendChild( document.createTextNode( ' ' + p.label ) );
			container.appendChild( span );
		} );

		wrapper.style.display = '';
	}

	function renderSerpPreview( result ) {
		var urlEl = document.getElementById( 'mc-serp-url' );
		var titleEl = document.getElementById( 'mc-serp-title' );
		var descEl = document.getElementById( 'mc-serp-desc' );

		if ( urlEl && result.post_url ) { urlEl.textContent = result.post_url; }
		if ( titleEl ) { titleEl.textContent = ( result.post_title || 'Untitled' ) + ' | ' + ( document.title.split( '\u2039' )[ 1 ] || '' ).trim(); }
		if ( descEl ) { descEl.textContent = result.meta_description || 'No meta description available. Add an excerpt or enable auto meta tags.'; }
	}

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

		// Header.
		var header = createEl( 'div', null, 'mc-seo-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-seo-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-seo-check-score mc-text-' + scoreClass( analyzerData.score ) );
		header.appendChild( scoreText );
		card.appendChild( header );

		// Progress bar.
		var progressWrap = createEl( 'div', null, 'mc-progress-bar mc-seo-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-seo-checklist' );

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

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

				var iconCircle = createEl( 'div', null, 'mc-seo-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-seo-check-content' );
				content.appendChild( createEl( 'div', check.label || '', 'mc-seo-check-title' ) );
				content.appendChild( createEl( 'div', check.message || '', 'mc-seo-check-desc' ) );
				if ( check.value ) { content.appendChild( createEl( 'div', check.value, 'mc-seo-check-value' ) ); }

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

					var fixUrl = getFixUrl( fixData.action );
					if ( fixUrl && fixData.actionLabel ) {
						var fixBtn = document.createElement( 'a' );
						fixBtn.href = fixUrl;
						fixBtn.className = 'mc-btn mc-btn-xs mc-btn-primary mc-seo-fix-btn';
						fixBtn.textContent = fixData.actionLabel;
						fixBtn.appendChild( document.createTextNode( ' ' ) );
						fixBtn.appendChild( createEl( 'i', null, 'fa-duotone fa-arrow-up-right-from-square' ) );
						fixPanel.appendChild( fixBtn );
					}

					content.appendChild( fixPanel );
				}

				li.appendChild( content );

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

					li.setAttribute( 'role', 'button' );
					li.setAttribute( 'tabindex', '0' );
					li.setAttribute( 'aria-expanded', 'false' );

					var toggleExpand = ( function ( item ) {
						return function ( e ) {
							if ( e.target.closest( '.mc-seo-fix-btn' ) ) { return; }
							var expanded = item.classList.toggle( 'is-expanded' );
							item.setAttribute( 'aria-expanded', String( expanded ) );
						};
					} )( li );

					li.addEventListener( 'click', toggleExpand );
					li.addEventListener( 'keydown', function ( e ) {
						if ( 'Enter' === e.key || ' ' === e.key ) {
							e.preventDefault();
							toggleExpand( e );
						}
					} );
				}

				list.appendChild( li );
			} );

			card.appendChild( list );
		}

		return card;
	}

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

		var priority = { fail: 0, warning: 1, pass: 2 };
		var items = [];

		categoryMaps.forEach( function ( categoryMap ) {
			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', 'No data available.', 'mc-text-medium' ) );
			return;
		}

		// Summary bar.
		var passing = items.filter( function ( i ) { return i.data.status === 'pass'; } ).length;
		var summary = createEl( 'div', null, 'mc-seo-tab-summary' );
		var avgScore = Math.round( items.reduce( function ( sum, i ) { return sum + i.data.score; }, 0 ) / items.length );
		summary.appendChild( createEl( 'span', passing + ' of ' + items.length + ' checks passing', 'mc-text-medium' ) );
		var summaryBadge = createEl( 'span', avgScore + '/100 avg', 'mc-badge mc-badge-' + ( STATUS_BADGE[ avgScore >= 80 ? 'pass' : ( avgScore >= 50 ? 'warning' : 'fail' ) ] ) );
		summary.appendChild( summaryBadge );
		grid.appendChild( summary );

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

			if ( item.data.status === 'pass' ) {
				card.classList.add( 'is-collapsible', 'is-collapsed' );

				var toggleBtn = document.createElement( 'button' );
				toggleBtn.type = 'button';
				toggleBtn.className = 'mc-seo-collapse-toggle';
				toggleBtn.setAttribute( 'aria-expanded', 'false' );
				toggleBtn.setAttribute( 'aria-label', meta.label + ' details' );
				toggleBtn.appendChild( createEl( 'span', 'Details' ) );
				toggleBtn.appendChild( createEl( 'i', null, 'fa-duotone fa-chevron-up' ) );
				card.appendChild( toggleBtn );

				toggleBtn.addEventListener( 'click', function ( e ) {
					e.stopPropagation();
					var collapsed = card.classList.toggle( 'is-collapsed' );
					toggleBtn.setAttribute( 'aria-expanded', String( ! collapsed ) );
				} );
			}

			grid.appendChild( card );
		} );

		grid.style.display = '';
	}

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

	var loadingTimer = null;

	function startLoadingSteps() {
		var steps = document.querySelectorAll( '.mc-seo-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;
			}
		}, 600 );
	}

	function stopLoadingSteps() {
		if ( loadingTimer ) { clearInterval( loadingTimer ); loadingTimer = null; }
		var steps = document.querySelectorAll( '.mc-seo-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-seo-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'; }
		} );
	}

	// ── Site Health (Section 1) ──────────────────────────────────────

	function loadSiteHealth() {
		var loadingEl = document.getElementById( 'mc-site-health-loading' );

		api.apiFetch( '/seo/site-health', { method: 'GET' } )
			.then( function ( response ) {
				var data = response.data || response;

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

				// Protections banner.
				renderProtections( data.protections );

				// Site health checks grid.
				renderChecksGrid( 'mc-site-health-grid', [ SITE_CATEGORIES ], data.analyzers || {} );
			} )
			.catch( function () {
				if ( loadingEl ) { loadingEl.textContent = 'Failed to load site health.'; }
			} );
	}

	// ── Page Analysis (Section 2) ────────────────────────────────────

	function runPageScan( postId ) {
		var loadingEl = document.getElementById( 'mc-seo-loading' );
		var resultsEl = document.getElementById( 'mc-seo-results' );
		var emptyEl = document.getElementById( 'mc-seo-empty' );
		var btn = document.getElementById( 'mc-seo-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();

		var id = parseInt( postId, 10 ) || 0;

		api.apiFetch( '/seo/scan', {
			method: 'POST',
			body: JSON.stringify( { post_id: id } ),
		} )
			.then( function ( data ) {
				stopLoadingSteps();
				setTimeout( function () {
					if ( btn ) { setLoading( btn, false ); }
					renderPageResults( data );
					api.notify( 'Page 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 || 'Scan failed. Please try again.', 'error' );
			} );
	}

	function renderPageResults( data ) {
		var loadingEl = document.getElementById( 'mc-seo-loading' );
		var resultsEl = document.getElementById( 'mc-seo-results' );
		var emptyEl = document.getElementById( 'mc-seo-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 : ( result.score || 0 );
		var analyzers = result.analyzers || {};

		currentPostId = result.post_id || 0;

		// Hero.
		animateScoreRing( score );

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

		var title = document.getElementById( 'mc-seo-hero-title' );
		if ( title && result.post_title ) { title.textContent = 'Monitor.Cat SEO & GEO Score'; }

		renderHeroBadges( analyzers );

		// SERP preview.
		renderSerpPreview( result );

		// Page checks grid (only page-specific categories).
		renderChecksGrid( 'mc-seo-page-checks', [ PAGE_CATEGORIES ], analyzers );
	}

	// ── Tooltip ──────────────────────────────────────────────────────

	function initTooltip() {
		var tip = document.getElementById( 'mc-seo-deeplink-tip' );
		if ( ! tip ) { return; }

		// Check if already dismissed.
		try {
			if ( localStorage.getItem( TOOLTIP_STORAGE_KEY ) ) { return; }
		} catch ( e ) {
			// localStorage unavailable, show anyway.
		}

		tip.style.display = '';

		var closeBtn = tip.querySelector( '.mc-seo-tooltip-close' );
		if ( closeBtn ) {
			closeBtn.addEventListener( 'click', function () {
				tip.style.display = 'none';
				try { localStorage.setItem( TOOLTIP_STORAGE_KEY, '1' ); } catch ( e ) { /* noop */ }
			} );
		}
	}

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

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

		// 1. Load site health immediately (no page selection needed).
		loadSiteHealth();

		// 2. Load posts dropdown, then auto-scan the first one.
		var select = document.getElementById( 'mc-seo-post-select' );

		// Enhance native select into custom dropdown.
		if ( select && api.enhanceSelect ) {
			api.enhanceSelect( select, { size: 'sm' } );
		}

		api.apiFetch( '/seo/posts', { method: 'GET' } )
			.then( function ( posts ) {
				if ( ! select ) { return; }
				while ( select.firstChild ) { select.removeChild( select.firstChild ); }

				if ( Array.isArray( posts ) ) {
					posts.forEach( function ( post ) {
						var opt = document.createElement( 'option' );
						opt.value = String( post.id );
						opt.textContent = post.title + ( post.type && post.type !== 'homepage' ? ' (' + post.type + ')' : '' );
						select.appendChild( opt );
					} );
				}

				if ( select.options.length > 0 ) {
					select.selectedIndex = 0;
					// Show the loading state for page scan.
					var loadingEl = document.getElementById( 'mc-seo-loading' );
					if ( loadingEl ) { loadingEl.style.display = ''; }
					runPageScan( select.value );
				}
			} )
			.catch( function () {
				var loadingEl = document.getElementById( 'mc-seo-loading' );
				if ( loadingEl ) { loadingEl.style.display = ''; }
				runPageScan( 1 );
			} );

		// Rescan button.
		var scanBtn = document.getElementById( 'mc-seo-scan-btn' );
		if ( scanBtn ) {
			scanBtn.addEventListener( 'click', function () {
				var postId = select ? select.value : '0';
				runPageScan( postId || '0' );
			} );
		}

		// Scan on dropdown change.
		if ( select ) {
			select.addEventListener( 'change', function () {
				if ( select.value !== '' ) { runPageScan( select.value ); }
			} );
		}

		// 3. Init tooltip.
		initTooltip();
	} );
} )();
