import React, { useEffect, useState } from 'react';
import { __, sprintf } from '@wordpress/i18n';
import { api } from '../api';
import { Card, Button, Notice, MetricGrid, Badge } from './ui';
import Explain from './Explain';
import { IconRefresh, IconExternal } from './icons';

/**
 * The catalogue audit.
 *
 * Product SEO fails in a small number of ways and all of them are countable,
 * so this counts them rather than offering advice. The ordering is by what
 * each one costs: index bloat first because it is the most damaging and the
 * least visible, then dead ends, then the data gaps.
 */
export default function StoreAudit() {
	const [data, setData] = useState(null);
	const [error, setError] = useState(null);
	const [busy, setBusy] = useState(false);

	const load = (fresh = false) => {
		setBusy(true);
		api
			.get(`/store/audit${fresh ? '?fresh=1' : ''}`)
			.then(setData)
			.catch((e) => setError(e.message))
			.finally(() => setBusy(false));
	};

	useEffect(() => {
		load();
	}, []);

	if (error) return <Notice tone="serious">{error}</Notice>;
	if (!data) return <Card>{__('Reading the catalogue…', 'ai-rank-suite')}</Card>;
	if (!data.active) return <Notice tone="warning">{__('WooCommerce is not active on this site.', 'ai-rank-suite')}</Notice>;

	const c = data.counts || {};
	const pct = (n) => (data.products > 0 ? Math.round((n / data.products) * 100) : 0);

	const go = (hash) => {
		window.location.hash = hash;
	};

	return (
		<div className="grid gap-3">
			<MetricGrid
				columns={4}
				metrics={[
					{
						id: 'products',
						label: __('Products', 'ai-rank-suite'),
						value: data.products.toLocaleString(),
						sub: __('published', 'ai-rank-suite'),
					},
					{
						id: 'stranded',
						label: __('Dead ends', 'ai-rank-suite'),
						hint: __('Out of stock and still indexable — a crawler is sent to a page nobody can buy from.', 'ai-rank-suite'),
						value: c.stranded ?? '—',
						accent: c.stranded > 0 ? 'var(--ars-c-red-ink)' : undefined,
						sub: __('out of stock, still indexable', 'ai-rank-suite'),
					},
					{
						id: 'thin',
						label: __('Thin descriptions', 'ai-rank-suite'),
						hint: __('Under 200 characters, there is nothing for a search engine to rank or an assistant to quote.', 'ai-rank-suite'),
						value: c.thin ?? '—',
						accent: pct(c.thin) > 25 ? 'var(--ars-c-red-ink)' : undefined,
						sub: sprintf(__('%d%% under 200 characters', 'ai-rank-suite'), pct(c.thin)),
					},
					{
						id: 'gtin',
						label: __('No GTIN', 'ai-rank-suite'),
						hint: __('Google cannot match the product to the same item elsewhere without a global identifier.', 'ai-rank-suite'),
						value: c.no_gtin ?? '—',
						accent: pct(c.no_gtin) > 50 ? 'var(--ars-accent)' : undefined,
						sub: sprintf(__('%d%% cannot be matched', 'ai-rank-suite'), pct(c.no_gtin)),
					},
				]}
			/>

			{(data.issues || []).length > 0 ? (
				<Card
					title={__('What is costing you traffic', 'ai-rank-suite')}
					subtitle={__('Ordered by consequence, not by count', 'ai-rank-suite')}
					action={
						<Button variant="ghost" busy={busy} onClick={() => load(true)}>
							<IconRefresh size={13} />{__('Re-check', 'ai-rank-suite')}</Button>
					}
				>
					<div className="grid gap-2">
						{data.issues.map((issue, i) => (
							<div key={i} className={`ars-head-issue is-${issue.level}`}>
								<span aria-hidden className="ars-head-issue-mark">
									{issue.level === 'error' ? '✕' : '!'}
								</span>
								<div>
									<div className="font-semibold text-[12.5px]">{issue.title}</div>
									<div className="text-[12px] mt-0.5" style={{ color: 'var(--ars-ink-2)' }}>
										{issue.text}
									</div>
									{FIX[issue.fix] && (
										<button
											type="button"
											className="ars-linkbtn mt-1.5"
											onClick={() => go(FIX[issue.fix].hash)}
										>
											{FIX[issue.fix].label} →
										</button>
									)}
								</div>
							</div>
						))}
					</div>
				</Card>
			) : (
				<Notice tone="good">{__('Nothing in the catalogue is failing the checks above.', 'ai-rank-suite')}</Notice>
			)}

			<div className="grid gap-3 lg:grid-cols-2">
				<Card title={__('Product data', 'ai-rank-suite')} subtitle={__('What each listing is missing', 'ai-rank-suite')} flush>
					<div className="ars-table-wrap">
						<table className="ars-table">
							<tbody>
								{[
									[__('No SKU', 'ai-rank-suite'), c.no_sku, __('Not required by Google, but every feed and every integration wants one.', 'ai-rank-suite')],
									[
										__('No GTIN', 'ai-rank-suite'),
										c.no_gtin,
										__('Google cannot match the product to the same item elsewhere without it.', 'ai-rank-suite'),
									],
									[__('No price', 'ai-rank-suite'), c.no_price, __('A product with no price cannot be a rich result at all.', 'ai-rank-suite')],
									[__('No image', 'ai-rank-suite'), c.no_image, __('No Shopping listing, no image in the result, a grey box when shared.', 'ai-rank-suite')],
									[
										__('No short description', 'ai-rank-suite'),
										c.no_short_desc,
										__('WooCommerce shows it beside the price; it is also the best source for a meta description.', 'ai-rank-suite'),
									],
									[
										__('No meta description', 'ai-rank-suite'),
										c.no_meta_desc,
										__('The autopilot can write these for the whole catalogue in one run.', 'ai-rank-suite'),
									],
									[__('Out of stock', 'ai-rank-suite'), c.out_of_stock, __('Fine in itself. The problem is only the indexable ones.', 'ai-rank-suite')],
								].map(([label, value, why]) => (
									<tr key={label}>
										<td>
											<div className="font-medium">{label}</div>
											<div className="t-caption">{why}</div>
										</td>
										<td className="is-num is-narrow tabular-nums">
											<b style={{ color: value > 0 ? 'var(--ars-ink)' : 'var(--ars-ink-3)' }}>{value}</b>
											{value > 0 && data.products > 0 && (
												<div className="t-caption">{pct(value)}%</div>
											)}
										</td>
									</tr>
								))}
							</tbody>
						</table>
					</div>
				</Card>

				<Card
					title={__('Category pages with no text', 'ai-rank-suite')}
					subtitle={__('Biggest first — a description on a category with 400 products is worth 400 times the one on a category with one', 'ai-rank-suite')}
					flush
				>
					{(data.categories?.rows || []).length === 0 ? (
						<p className="m-0 p-4 text-[13px]" style={{ color: 'var(--ars-ink-2)' }}>{__('Every category with products in it has a description.', 'ai-rank-suite')}</p>
					) : (
						<div className="ars-table-wrap">
							<table className="ars-table">
								<thead>
									<tr>
										<th>{__('Category', 'ai-rank-suite')}</th>
										<th className="is-num is-narrow">{__('Products', 'ai-rank-suite')}</th>
										<th className="is-num is-narrow">{__('Words', 'ai-rank-suite')}</th>
									</tr>
								</thead>
								<tbody>
									{data.categories.rows.map((r) => (
										<tr key={r.id}>
											<td className="font-medium">
												<a href={r.url} target="_blank" rel="noreferrer" className="inline-flex items-center gap-1">
													{r.name} <IconExternal size={10} />
												</a>
											</td>
											<td className="is-num is-narrow tabular-nums">{r.products}</td>
											<td className="is-num is-narrow tabular-nums">{r.words}</td>
										</tr>
									))}
								</tbody>
							</table>
						</div>
					)}
				</Card>
			</div>

			<Card
				title={__('Faceted navigation', 'ai-rank-suite')}
				subtitle={__('The filter URLs a crawler can reach, and whether anything stops it', 'ai-rank-suite')}
			>
				<MetricGrid
					columns={3}
					metrics={[
						{
							id: 'attributes',
							label: __('Filter attributes', 'ai-rank-suite'),
							hint: __('Colour, size, brand and so on — each one multiplies the crawlable URL space.', 'ai-rank-suite'),
							value: (data.facets?.attributes || []).length,
						},
						{
							id: 'combos',
							label: __('Possible combinations', 'ai-rank-suite'),
							hint: __('Each combination is a crawlable near-duplicate competing with the category page it came from.', 'ai-rank-suite'),
							value: (data.facets?.combos || 0).toLocaleString(),
							accent: data.facets?.combos > 100 ? 'var(--ars-c-red-ink)' : undefined,
						},
						{
							id: 'open',
							label: __('Unblocked parameters', 'ai-rank-suite'),
							hint: __('Filter parameters no robots.txt rule names — a crawler may follow every combination of them.', 'ai-rank-suite'),
							value: (data.facets?.open || []).length,
							accent: (data.facets?.open || []).length > 0 ? 'var(--ars-accent)' : undefined,
							sub: sprintf(__('%d named in robots.txt', 'ai-rank-suite'), (data.facets?.guarded || []).length),
						},
					]}
				/>

				<div className="mt-3 flex flex-wrap gap-1.5">
					{(data.facets?.guarded || []).map((p) => (
						<span key={p} className="ars-tag" style={{ background: 'var(--ars-c-green)', color: 'var(--ars-c-green-ink)' }}>
							{p}
						</span>
					))}
					{(data.facets?.open || []).map((p) => (
						<span key={p} className="ars-tag">
							{p}
						</span>
					))}
				</div>

				<Explain title={__('Why this is the most damaging problem a shop can have', 'ai-rank-suite')}>
					<p>
						{__('A shop with six filter attributes can generate more crawlable URLs than it has products — every one a near-duplicate of a category page, every one competing with the category page it came from. Google spends its crawl budget on them instead of your products, and the category page it should have ranked is diluted across a thousand variants of itself.', 'ai-rank-suite')}
					</p>
					<p>
						{__('None of those URLs exist until a crawler follows a filter link, which is why the problem is invisible from the admin and why it is usually found months later in a Search Console coverage report. The fix is to disallow the parameters in robots.txt — the AI Crawlers screen writes robots.txt, and the Advanced screen has the raw editor.', 'ai-rank-suite')}
					</p>
					<p>
						{__('The count above is the number of parameters in play and whether anything names them in robots.txt. It is deliberately not a count of junk URLs, because nobody can know that without crawling the site, and a made-up number here would be worse than none.', 'ai-rank-suite')}
					</p>
				</Explain>
			</Card>

			{(data.thin_list || []).length > 0 && (
				<Card
					title={__('The thinnest products', 'ai-rank-suite')}
					subtitle={__('Shortest first — the autopilot can write descriptions for all of them', 'ai-rank-suite')}
					action={
						<Button variant="ghost" onClick={() => go('/autopilot')}>{__('Open the autopilot', 'ai-rank-suite')}</Button>
					}
					flush
				>
					<div className="ars-table-wrap">
						<table className="ars-table">
							<thead>
								<tr>
									<th>{__('Product', 'ai-rank-suite')}</th>
									<th className="is-mid" style={{ width: 120 }}>{__('SKU', 'ai-rank-suite')}</th>
									<th className="is-num is-narrow">{__('Characters', 'ai-rank-suite')}</th>
								</tr>
							</thead>
							<tbody>
								{data.thin_list.map((p) => (
									<tr key={p.id} style={{ cursor: 'pointer' }} onClick={() => go(`/content/${p.id}`)}>
										<td className="font-medium truncate">{p.title}</td>
										<td className="is-mid t-caption">{p.sku || '—'}</td>
										<td className="is-num is-narrow tabular-nums">
											{p.body === 0 ? <Badge tone="serious">{__('empty', 'ai-rank-suite')}</Badge> : p.body}
										</td>
									</tr>
								))}
							</tbody>
						</table>
					</div>
				</Card>
			)}
		</div>
	);
}

const FIX = {
	crawl: { hash: '/crawlers', label: __('Open crawler controls', 'ai-rank-suite') },
	content: { hash: '/content?type=product', label: __('Open the product list', 'ai-rank-suite') },
	products: { hash: '/content?type=product', label: __('Open the product list', 'ai-rank-suite') },
	categories: { hash: '/schema', label: __('Open schema settings', 'ai-rank-suite') },
	autopilot: { hash: '/autopilot', label: __('Let the autopilot write them', 'ai-rank-suite') },
};
