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

/**
 * Word counts across the site.
 *
 * The bands are the useful part, not the average. An average of 640 words
 * hides a site where half the pages are 1,200 and half are 80 — and the 80s
 * are the whole problem. So the distribution comes first and the average is a
 * footnote.
 */
const TONE = {
	empty: '#c0392b',
	thin: '#e2952b',
	standard: '#4436c8',
	deep: '#2b7a4b',
	long: '#8b5cf0',
	unknown: '#b7bcca',
};

export default function WordStats({ onOpen }) {
	const [data, setData] = useState(null);
	const [error, setError] = useState(null);
	const [busy, setBusy] = useState(false);

	const load = (fresh = false) => {
		setBusy(true);
		api
			.get(`/content/words${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>{__('Counting…', 'ai-rank-suite')}</Card>;

	const bands = data.bands || {};
	const catalog = data.catalog || [];
	const known = (data.posts || 0) - (bands.unknown || 0);

	return (
		<div className="grid gap-3">
			<MetricGrid
				columns={4}
				metrics={[
					{
						id: 'words',
						label: __('Words on the site', 'ai-rank-suite'),
						hint: __('Counted from the rendered page, not the raw post content. Reading time assumes 220 words per minute.', 'ai-rank-suite'),
						value: (data.words || 0).toLocaleString(),
						sub: sprintf(__('about %s minutes of reading', 'ai-rank-suite'), (data.reading || 0).toLocaleString()),
					},
					{
						id: 'average',
						label: __('Average page', 'ai-rank-suite'),
						hint: __('The distribution below matters more — an average of 640 can hide half the site at 80 words.', 'ai-rank-suite'),
						value: known > 0 ? data.average || 0 : '—',
						sub: known > 0 ? sprintf(__('across %s counted pages', 'ai-rank-suite'), known.toLocaleString()) : __('nothing counted yet', 'ai-rank-suite'),
					},
					{
						id: 'thin',
						label: __('Thin or empty', 'ai-rank-suite'),
						hint: __('Too little for an assistant to quote or a search engine to rank.', 'ai-rank-suite'),
						value: (bands.thin || 0) + (bands.empty || 0),
						accent: (bands.thin || 0) + (bands.empty || 0) > 0 ? 'var(--ars-accent)' : undefined,
						sub: __('under 300 words', 'ai-rank-suite'),
					},
					{
						id: 'deep',
						label: __('In depth', 'ai-rank-suite'),
						value: (bands.deep || 0) + (bands.long || 0),
						sub: __('800 words and over', 'ai-rank-suite'),
					},
				]}
			/>

			<Card
				icon={<IconDoc size={16} />}
				title={__('How long your pages are', 'ai-rank-suite')}
				subtitle={__('Counted from the rendered page, not the raw post content — so a page built entirely of blocks is counted properly', 'ai-rank-suite')}
				action={
					<Button variant="ghost" busy={busy} onClick={() => load(true)}>
						<IconRefresh size={13} />{__('Recount', 'ai-rank-suite')}</Button>
				}
			>
				{/*
				 * The bar describes the pages that have been counted, and only
				 * those.
				 *
				 * "Not counted yet" used to be a band inside it, so on a site
				 * where most pages have never been analysed the distribution was
				 * four fifths grey and the real shape was unreadable — and worse,
				 * it implied a measurement where there is none. Coverage is now
				 * stated above the bar as what it is: how much of the site the
				 * bar speaks for.
				 */}
				{(() => {
					const counted = catalog.reduce((n, b) => n + (bands[b.id] || 0), 0);
					const unknown = bands.unknown || 0;
					const total = counted + unknown;
					const pct = (n) => (counted > 0 ? Math.round((100 * n) / counted) : 0);

					return (
						<div className="grid gap-3">
							<div className="flex items-center justify-between gap-3 flex-wrap">
								<span className="text-[13px] font-semibold">
									{sprintf(_n('%s page counted', '%s pages counted', counted, 'ai-rank-suite'), counted.toLocaleString())}
								</span>
								<span className="t-caption">
									{total > 0 ? sprintf(__('%1$s%% of %2$s published', 'ai-rank-suite'), Math.round((100 * counted) / total), total.toLocaleString()) : __('nothing published', 'ai-rank-suite')}
								</span>
							</div>

							{counted === 0 ? (
								<div className="ars-empty-band">{__('Nothing has been counted yet — run the site audit and this fills in.', 'ai-rank-suite')}</div>
							) : (
								<>
									<SegmentBar
										height={16}
										segments={catalog.map((b) => ({
											label: b.label,
											value: bands[b.id] || 0,
											color: TONE[b.id],
										}))}
									/>

									{/* Each band is a row with its share, and a row is a
									    filter: the Pages tab can show exactly these. */}
									<div className="ars-bands">
										{catalog.map((b) => {
											const n = bands[b.id] || 0;
											return (
												<div key={b.id} className={`ars-band${n === 0 ? ' is-zero' : ''}`}>
													<span className="ars-band-swatch" style={{ background: TONE[b.id] }} aria-hidden />
													<span className="ars-band-label">{b.label}</span>
													<span className="ars-band-n tabular-nums">{n.toLocaleString()}</span>
													<span className="ars-band-pct tabular-nums">{pct(n)}%</span>
													<span className="ars-band-note-text">{b.note}</span>
												</div>
											);
										})}
									</div>
								</>
							)}

							{unknown > 0 && (
								<Notice tone="warning">
									{sprintf(
										_n(
											'%s published page has never been analysed, so it is not in the bar above at all — counting it as empty would be a guess. Run the site audit, or use the analyzer on the dashboard, and it joins the distribution.',
											'%s published pages have never been analysed, so they are not in the bar above at all — counting them as empty would be a guess. Run the site audit, or use the analyzer on the dashboard, and they join the distribution.',
											unknown,
											'ai-rank-suite'
										),
										unknown.toLocaleString()
									)}
								</Notice>
							)}
						</div>
					);
				})()}
			</Card>

			<div className="grid gap-3 lg:grid-cols-2">
				<Card title={__('By content type', 'ai-rank-suite')} flush>
					<div className="ars-table-wrap">
						<table className="ars-table">
							<thead>
								<tr>
									<th>{__('Type', 'ai-rank-suite')}</th>
									<th className="is-num is-narrow">{__('Pages', 'ai-rank-suite')}</th>
									<th className="is-num is-narrow">{__('Average', 'ai-rank-suite')}</th>
									<th className="is-num is-narrow">{__('Longest', 'ai-rank-suite')}</th>
									<th style={{ width: 150 }}>{__('Spread', 'ai-rank-suite')}</th>
								</tr>
							</thead>
							<tbody>
								{(data.types || []).map((t) => (
									<tr key={t.type}>
										<td className="font-medium">{t.label}</td>
										<td className="is-num is-narrow tabular-nums">{t.total.toLocaleString()}</td>
										<td className="is-num is-narrow tabular-nums">{t.average ?? '—'}</td>
										<td className="is-num is-narrow tabular-nums">{t.longest.toLocaleString()}</td>
										<td>
											<SegmentBar
												height={8}
												showLegend={false}
												segments={catalog.map((b) => ({
													label: b.label,
													value: t.bands[b.id] || 0,
													color: TONE[b.id],
												}))}
											/>
										</td>
									</tr>
								))}
							</tbody>
						</table>
					</div>
				</Card>

				<Card title={__('The shortest published pages', 'ai-rank-suite')} subtitle={__('Where the work is, in order', 'ai-rank-suite')} flush>
					<div className="ars-table-wrap">
						<table className="ars-table">
							<thead>
								<tr>
									<th>{__('Page', 'ai-rank-suite')}</th>
									<th className="is-num is-narrow">{__('Words', 'ai-rank-suite')}</th>
								</tr>
							</thead>
							<tbody>
								{(data.shortest || []).map((p) => (
									<tr
										key={p.id}
										onClick={() => onOpen?.(p.id)}
										style={onOpen ? { cursor: 'pointer' } : undefined}
									>
										<td className="truncate">{p.title || `#${p.id}`}</td>
										<td className="is-num is-narrow tabular-nums">
											<b style={{ color: p.words < 300 ? 'var(--ars-serious)' : 'inherit' }}>{p.words}</b>
										</td>
									</tr>
								))}
							</tbody>
						</table>
					</div>
				</Card>
			</div>

			<Explain title={__('Why this number differs from the one in the editor', 'ai-rank-suite')}>
				<p>
					{__('WordPress counts the raw post content, so it counts shortcode attributes, block comments and the alt text inside an image block — and it counts nothing that a block renders at display time. On a site built with blocks or a page builder the two numbers can differ by hundreds of words.', 'ai-rank-suite')}
				</p>
				<p>
					{__('This counts the rendered page, which is what a crawler and an assistant actually read. It is stored on each post when the page is analyzed, so listing a thousand rows does not mean rendering a thousand pages.', 'ai-rank-suite')}
				</p>
				<p>
					{__('Reading time uses 220 words per minute, the middle of the range for adult silent reading of general prose. Treat it as an estimate, not a measurement.', 'ai-rank-suite')}
				</p>
			</Explain>
		</div>
	);
}
