import { __, _n, sprintf } from '@wordpress/i18n';
import React, { useCallback, useEffect, useState } from 'react';
import { api } from '../api';
import ScreenVerdict from '../components/ScreenVerdict';
import { Card, Button, Badge, Notice, MetricGrid, FilterBar, ChipBar, Field, RankBar, Segmented, PageState, LineChart, Delta } from '../components/ui';
import Explain from '../components/Explain';
import { IconLink, IconRefresh, IconSearch, IconExternal, IconX } from '../components/icons';

/**
 * Backlinks.
 *
 * The honest version. No plugin can produce an Ahrefs-style index from inside
 * a WordPress install, so this is built around the two things a site really
 * knows — who sends it visitors, and what a source page says when you read it
 * — plus Bing's free index for anyone who wants breadth. Every row says where
 * it came from.
 */

const STATUS = {
	live: { tone: 'good', label: __('Live', 'ai-rank-suite'), why: __('Read the page; the link is there and followed.', 'ai-rank-suite') },
	nofollow: { tone: 'neutral', label: __('Nofollow', 'ai-rank-suite'), why: __('The link is there but carries rel=nofollow, ugc or sponsored.', 'ai-rank-suite') },
	lost: { tone: 'serious', label: __('Lost', 'ai-rank-suite'), why: __('We read the page and the link is no longer on it.', 'ai-rank-suite') },
	unreachable: { tone: 'warning', label: __('Unreachable', 'ai-rank-suite'), why: __('The source did not answer. Not the same as removed.', 'ai-rank-suite') },
	unverified: { tone: 'brand', label: __('Unverified', 'ai-rank-suite'), why: __('Known from a visit or an import; not read yet.', 'ai-rank-suite') },
};

const VIA = {
	referrer: __('A real visitor arrived through it', 'ai-rank-suite'),
	bing: 'Bing Webmaster Tools',
	import: __('Imported by you', 'ai-rank-suite'),
};

export default function Backlinks() {
	const [data, setData] = useState(null);
	const [error, setError] = useState(null);
	const [busy, setBusy] = useState(false);
	const [status, setStatus] = useState('');
	const [growth, setGrowth] = useState(null);
	const [via, setVia] = useState('');
	const [search, setSearch] = useState('');
	const [page, setPage] = useState(1);
	const [view, setView] = useState('links');
	const [bingKey, setBingKey] = useState('');
	const [note, setNote] = useState(null);

	const load = useCallback(
		async (p = page, st = status, v = via, q = search) => {
			try {
				const params = new URLSearchParams({
					page: String(p),
					per_page: '25',
					status: st,
					via: v,
					search: q,
				});
				setData(await api.get(`/backlinks?${params}`));
				setError(null);
			} catch (e) {
				setError(e.message);
			}
		},
		[page, status, via, search]
	);

	useEffect(() => {
		load(page, status, via, search);
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [page, status, via]);

	useEffect(() => {
		api.get('/backlinks/growth?weeks=26').then((r) => setGrowth(r.weeks || [])).catch(() => setGrowth([]));
	}, []);

	if (!data) return <PageState error={error} />;

	const s = data.summary || {};
	const pages = Math.max(1, Math.ceil((data.total || 0) / 25));

	const verify = async (ids) => {
		setBusy(true);
		setNote(null);
		try {
			const r = await api.post('/backlinks/verify', { ids: ids || [] });
			setNote(
				r.checked === 0
					? __('Nothing was waiting to be checked — every link has been read in the last week.', 'ai-rank-suite')
					: sprintf(_n('Read %1$d source page. %2$d still queued.', 'Read %1$d source pages. %2$d still queued.', r.checked, 'ai-rank-suite'), r.checked, r.pending)
			);
			await load();
		} catch (e) {
			setError(e.message);
		} finally {
			setBusy(false);
		}
	};

	const importBing = async () => {
		setBusy(true);
		setNote(null);
		try {
			const r = await api.post('/backlinks/bing');
			setNote(sprintf(__('Bing returned %1$s links across %2$s of your pages.', 'ai-rank-suite'), r.imported, r.pages));
			await load();
		} catch (e) {
			setError(e.message);
		} finally {
			setBusy(false);
		}
	};

	const saveBing = async () => {
		setBusy(true);
		try {
			await api.put('/backlinks/bing', { key: bingKey });
			setBingKey('');
			await load();
		} catch (e) {
			setError(e.message);
		} finally {
			setBusy(false);
		}
	};

	const forget = async (id) => {
		await api.del(`/backlinks/${id}`);
		load();
	};

	return (
		<div className="ars-page">
			{error && <Notice tone="serious">{error}</Notice>}
			{note && <Notice tone="good">{note}</Notice>}

			{/*
			 * Zero backlinks and zero connected sources look identical in a row
			 * of zeroes, and they mean opposite things: one is a site nobody
			 * links to, the other is a screen that has never been given anything
			 * to read. Say which.
			 */}
			<ScreenVerdict
				{...(() => {
					const sum = data?.summary || {};
					const links = sum.total || 0;
					// The API reports the one source it can read: Bing.
					const connected = !!data?.bing?.connected;
					if (!connected) {
						return {
							tone: 'neutral',
							text: __('No backlink source is connected, so this screen has nothing to read.', 'ai-rank-suite'),
							why: __('Bing Webmaster Tools is free and is the one backlink index a site can read for its own domain. Connect it under Sources and the numbers below fill in.', 'ai-rank-suite'),
							action: __('Open Sources', 'ai-rank-suite'),
							onAction: () => setView('sources'),
						};
					}
					if (links === 0) {
						return {
							tone: 'warning',
							text: __('Connected, but no backlinks have come back yet.', 'ai-rank-suite'),
							why: __('Either the index genuinely has none for this domain, or the site is not verified in that account — Bing only returns links for a site you own there.', 'ai-rank-suite'),
						};
					}
					return {
						tone: sum.lost > 0 ? 'warning' : 'good',
						text: sprintf(
							/* translators: 1: links, 2: domains. */
							_n('%1$s link from %2$s domains.', '%1$s links from %2$s domains.', links, 'ai-rank-suite'),
							links.toLocaleString(),
							(sum.domains || 0).toLocaleString()
						),
						why:
							sum.lost > 0
								? sprintf(__('%s were there before and are not now — a lost link is worth chasing while the editor still remembers the page.', 'ai-rank-suite'), sum.lost.toLocaleString())
								: __('Nothing has been lost since the last check. The anchors below show what those links say you are about.', 'ai-rank-suite'),
					};
				})()}
			/>

			{/*
			 * Four toned tiles became one bordered grid. The sentence under each
			 * tile is a `?` hover now; what remains under a number is a data fact.
			 * Colour is reserved for the one genuine alert — links that are gone.
			 */}
			<MetricGrid
				columns={4}
				metrics={[
					{
						id: 'domains',
						label: __('Referring domains', 'ai-rank-suite'),
						hint: __('Distinct sites known to link here — from visitors, Bing and your own imports.', 'ai-rank-suite'),
						value: s.domains ?? '—',
						sub: sprintf(_n('%s link in total', '%s links in total', s.total || 0, 'ai-rank-suite'), (s.total || 0).toLocaleString()),
					},
					{
						id: 'live',
						label: __('Verified live', 'ai-rank-suite'),
						hint: __('The source page was fetched and read: the link is there and followed.', 'ai-rank-suite'),
						value: s.live ?? '—',
						sub: s.nofollow ? sprintf(__('%d more are nofollow', 'ai-rank-suite'), s.nofollow) : undefined,
					},
					{
						id: 'lost',
						label: __('Lost', 'ai-rank-suite'),
						hint: __('The source page was read again and the link is no longer on it — a claim worth trusting, unlike an index that last crawled months ago.', 'ai-rank-suite'),
						value: s.lost ?? '—',
						accent: s.lost > 0 ? 'var(--ars-c-red-ink)' : undefined,
					},
					{
						id: 'clicks',
						label: __('Clicks through', 'ai-rank-suite'),
						hint: __('Visits that arrived by a link — the links that actually send you people.', 'ai-rank-suite'),
						value: s.clicks ?? '—',
					},
				]}
			/>

			{/* Cumulative, from first_seen — "are we earning links" is a line
			    that climbs, not a bar chart of weekly noise. Two points minimum,
			    or there is no trend to claim. */}
			{growth && growth.length > 1 && (
				<Card
					title={__('Backlink profile over time', 'ai-rank-suite')}
					subtitle={__('Every link this site knows about, accumulated week by week', 'ai-rank-suite')}
					action={<Delta value={(growth[growth.length - 1]?.value ?? 0) - (growth[0]?.value ?? 0)} suffix={` ${__('in this window', 'ai-rank-suite')}`} />}
				>
					<LineChart
						data={growth}
						label={__('Known backlinks', 'ai-rank-suite')}
						color="var(--ars-series-4)"
						height={140}
						formatValue={(v) => `${v}`}
					/>
				</Card>
			)}

			<Segmented
				value={view}
				onChange={setView}
				label={__('View', 'ai-rank-suite')}
				options={[
					{ id: 'links', label: sprintf(__('Links (%s)', 'ai-rank-suite'), (data.total || 0).toLocaleString()) },
					{ id: 'domains', label: sprintf(__('Domains (%s)', 'ai-rank-suite'), s.domains || 0) },
					{ id: 'anchors', label: __('Anchors', 'ai-rank-suite') },
					{ id: 'sources', label: __('Sources', 'ai-rank-suite') },
				]}
			/>

			{view === 'links' && (
				<Card
					icon={<IconLink size={16} />}
					title={__('Every link we know about', 'ai-rank-suite')}
					subtitle={__('Where it came from, whether the page still carries it, and what the anchor says', 'ai-rank-suite')}
					action={
						<div className="flex items-center gap-2">
							{s.unverified > 0 && (
								<Badge tone="brand">{sprintf(__('%d not read yet', 'ai-rank-suite'), s.unverified)}</Badge>
							)}
							<Button variant="ghost" busy={busy} onClick={() => verify()}>
								<IconRefresh size={13} />{__('Check the next 10', 'ai-rank-suite')}</Button>
						</div>
					}
					flush
				>
					<FilterBar
						right={
							<ChipBar
								label={__('Found by', 'ai-rank-suite')}
								value={via}
								onChange={(v) => {
									setVia(v);
									setPage(1);
								}}
								options={[
									{ id: '', label: __('Any', 'ai-rank-suite') },
									{ id: 'referrer', label: __('Visitors', 'ai-rank-suite') },
									{ id: 'bing', label: __('Bing', 'ai-rank-suite') },
									{ id: 'import', label: __('Imported', 'ai-rank-suite') },
								]}
							/>
						}
					>
						<div className="ars-search">
							<IconSearch size={14} />
							<input
								type="search"
								value={search}
								placeholder={__('Domain or anchor text', 'ai-rank-suite')}
								onChange={(e) => setSearch(e.target.value)}
								onKeyDown={(e) => {
									if (e.key === 'Enter') {
										setPage(1);
										load(1, status, via, search);
									}
								}}
							/>
						</div>
						<ChipBar
							label={__('Status', 'ai-rank-suite')}
							value={status}
							onChange={(v) => {
								setStatus(v);
								setPage(1);
							}}
							options={[
								{ id: '', label: __('All', 'ai-rank-suite') },
								{ id: 'live', label: __('Live', 'ai-rank-suite') },
								{ id: 'nofollow', label: __('Nofollow', 'ai-rank-suite') },
								{ id: 'lost', label: __('Lost', 'ai-rank-suite') },
								{ id: 'unverified', label: __('Unverified', 'ai-rank-suite') },
								{ id: 'unreachable', label: __('Unreachable', 'ai-rank-suite') },
							]}
						/>
					</FilterBar>

					{data.rows.length === 0 ? (
						<div className="ars-empty">
							<IconLink size={22} />
							<div className="font-semibold mt-2">{__('No links recorded yet', 'ai-rank-suite')}</div>
							<p className="m-0 mt-1 text-[13px] max-w-[62ch] mx-auto" style={{ color: 'var(--ars-ink-2)' }}>
								{__('The list fills itself: every visitor who arrives from another site proves a link exists and gets recorded here. Connect Bing Webmaster Tools under Sources for the links nobody has clicked yet.', 'ai-rank-suite')}
							</p>
						</div>
					) : (
						<div className="ars-table-wrap">
							<table className="ars-table">
								<thead>
									<tr>
										<th style={{ width: 210 }}>{__('From', 'ai-rank-suite')}</th>
										<th>{__('Anchor', 'ai-rank-suite')}</th>
										<th style={{ width: 190 }}>To</th>
										<th className="is-mid" style={{ width: 108 }}>{__('Status', 'ai-rank-suite')}</th>
										<th className="is-num is-narrow">{__('Clicks', 'ai-rank-suite')}</th>
										<th className="is-mid" style={{ width: 92 }}>{__('Found by', 'ai-rank-suite')}</th>
										<th style={{ width: 34 }} aria-label={__('Remove', 'ai-rank-suite')} />
									</tr>
								</thead>
								<tbody>
									{data.rows.map((row) => {
										const meta = STATUS[row.status] || STATUS.unverified;
										return (
											<tr key={row.id}>
												<td>
													<a
														href={row.source}
														target="_blank"
														rel="noreferrer nofollow"
														className="inline-flex items-center gap-1 font-medium"
														title={row.source}
													>
														{row.domain} <IconExternal size={10} />
													</a>
												</td>
												<td style={{ color: 'var(--ars-ink-2)' }}>
													{row.anchor ? (
														<span className="truncate inline-block" style={{ maxWidth: 260 }}>
															{row.anchor}
														</span>
													) : (
														<i style={{ color: 'var(--ars-ink-3)' }}>{__('not read yet', 'ai-rank-suite')}</i>
													)}
												</td>
												<td className="truncate" style={{ color: 'var(--ars-ink-2)' }}>
													{row.post_title || row.target}
												</td>
												<td className="is-mid">
													<span title={meta.why}>
														<Badge tone={meta.tone}>{meta.label}</Badge>
													</span>
												</td>
												<td className="is-num is-narrow tabular-nums">{row.hits || '—'}</td>
												<td className="is-mid">
													<span className="ars-tag" title={VIA[row.via] || row.via}>
														{row.via}
													</span>
												</td>
												<td>
													<button
														type="button"
														className="ars-move"
														aria-label={__('Remove this link', 'ai-rank-suite')}
														title={__('Remove from the list', 'ai-rank-suite')}
														onClick={() => forget(row.id)}
													>
														<IconX size={12} />
													</button>
												</td>
											</tr>
										);
									})}
								</tbody>
							</table>
						</div>
					)}

					{pages > 1 && (
						<div className="flex items-center gap-2 p-3">
							<Button variant="ghost" disabled={page <= 1} onClick={() => setPage(page - 1)}>
								← Previous
							</Button>
							<span className="t-caption">
								{sprintf(
									/* translators: 1: current page number, 2: total pages. */
									__('Page %1$s of %2$s', 'ai-rank-suite'),
									page.toLocaleString(),
									pages.toLocaleString()
								)}
							</span>
							<Button variant="ghost" disabled={page >= pages} onClick={() => setPage(page + 1)}>{__('Next →', 'ai-rank-suite')}</Button>
						</div>
					)}
				</Card>
			)}

			{view === 'domains' && (
				<div className="grid gap-3 lg:grid-cols-2">
					<Card title={__('Who links to you most', 'ai-rank-suite')} subtitle={__('By number of linking pages', 'ai-rank-suite')} flush>
						{(s.top_domains || []).length === 0 ? (
							<p className="m-0 p-4 t-caption">{__('Nothing recorded yet.', 'ai-rank-suite')}</p>
						) : (
							<div className="p-4">
								<RankBar
									items={(s.top_domains || []).map((d) => ({ label: d.domain, value: d.links }))}
									max={Math.max(...(s.top_domains || [{ links: 1 }]).map((d) => d.links))}
									format={(v) => sprintf(_n('%d link', '%d links', v, 'ai-rank-suite'), v)}
								/>
							</div>
						)}
					</Card>
					<Card title={__('Which of your pages earn links', 'ai-rank-suite')} subtitle={__('By number of distinct referring domains', 'ai-rank-suite')} flush>
						{(s.top_pages || []).length === 0 ? (
							<p className="m-0 p-4 t-caption">{__('Nothing recorded yet.', 'ai-rank-suite')}</p>
						) : (
							<div className="p-4">
								<RankBar
									items={(s.top_pages || []).map((p) => ({ label: p.title || `#${p.post_id}`, value: p.domains }))}
									max={Math.max(...(s.top_pages || [{ domains: 1 }]).map((p) => p.domains))}
									format={(v) => `${v} domain${v === 1 ? '' : 's'}`}
									color="var(--ars-accent)"
								/>
							</div>
						)}
					</Card>
				</div>
			)}

			{view === 'anchors' && (
				<Card
					title={__('Anchor text', 'ai-rank-suite')}
					subtitle={__('What other sites call you — the phrase a search engine most strongly associates with the page', 'ai-rank-suite')}
					flush
				>
					{(s.anchors || []).length === 0 ? (
						<p className="m-0 p-4 text-[13px]" style={{ color: 'var(--ars-ink-2)' }}>{__('Anchors are read from the source page during verification, so this fills up as links are checked.', 'ai-rank-suite')}</p>
					) : (
						<div className="p-4">
							<RankBar
								items={(s.anchors || []).map((a) => ({ label: a.text, value: a.n }))}
								max={Math.max(...(s.anchors || [{ n: 1 }]).map((a) => a.n))}
								format={(v) => `${v}×`}
							/>
							<p className="m-0 mt-3 t-caption max-w-[70ch]">
								{__('A healthy profile is mostly your brand name and natural phrases. A single commercial keyword dominating the list is the pattern link schemes produce, and the pattern penalties look for.', 'ai-rank-suite')}
							</p>
						</div>
					)}
				</Card>
			)}

			{view === 'sources' && (
				<div className="grid gap-3">
					<Card
						title={__('Bing Webmaster Tools', 'ai-rank-suite')}
						subtitle={__('The one backlink index a site can read for free — generate an API key in Bing Webmaster Tools under Settings → API access', 'ai-rank-suite')}
						action={
							data.bing?.connected && (
								<Button busy={busy} onClick={importBing}>{__('Import links now', 'ai-rank-suite')}</Button>
							)
						}
					>
						<div className="grid gap-3 sm:grid-cols-2">
							<Field
								label={__('API key', 'ai-rank-suite')}
								hint={
									data.bing?.connected
										? sprintf(__('Stored (%s). Enter a new one to replace it.', 'ai-rank-suite'), data.bing.hint)
										: __('Stored encrypted. Bing only returns links for a site verified in your account.', 'ai-rank-suite')
								}
							>
								<input
									type="password"
									value={bingKey}
									autoComplete="off"
									placeholder={data.bing?.connected ? '••••••••' : __('Paste the key', 'ai-rank-suite')}
									onChange={(e) => setBingKey(e.target.value)}
								/>
							</Field>
							<div className="flex items-end gap-2">
								<Button variant="ghost" busy={busy} onClick={saveBing} disabled={!bingKey}>{__('Save key', 'ai-rank-suite')}</Button>
								{data.bing?.connected && <Badge tone="good">{__('Connected', 'ai-rank-suite')}</Badge>}
								{data.bing?.last > 0 && (
									<span className="t-caption">
										{sprintf(__('Last import %s', 'ai-rank-suite'), new Date(data.bing.last * 1000).toLocaleString())}
									</span>
								)}
							</div>
						</div>
					</Card>

					<Explain title={__('Where these numbers come from, and what they are not', 'ai-rank-suite')}>
						<p>
							{__('No plugin can produce an Ahrefs-style backlink index from inside a WordPress install — those are built by crawling the web for years. So this is built around three sources, and every row says which one it came from.', 'ai-rank-suite')}
						</p>
						<p>
							<b>{__('Visitors.', 'ai-rank-suite')}</b>{' '}
							{__('Someone arriving from another domain proves a link exists and that it is being clicked. That is a smaller set than a commercial index and a more useful one: these are the links that send you people. Note that a full-page cache serves most visits without PHP running, so a site behind one records fewer referrals than it receives.', 'ai-rank-suite')}
						</p>
						<p>
							<b>{__('Verification.', 'ai-rank-suite')}</b>{' '}
							{__('For any link here, the source page is fetched and read: is the link still on it, what does the anchor say, is it nofollow. A commercial index tells you a link existed when it last crawled. This tells you what the page says now — which is why “Lost” is a claim worth trusting, and why “Unreachable” is kept separate from it rather than counted as a removal.', 'ai-rank-suite')}
						</p>
						<p>
							<b>{__('Bing.', 'ai-rank-suite')}</b>{' '}
							{__('Free, real crawl data, limited to sites verified in your Webmaster Tools account and to Bing\'s own index, which is smaller than Google\'s. Useful for breadth; not a total.', 'ai-rank-suite')}
						</p>
					</Explain>
				</div>
			)}
		</div>
	);
}
