import React, { useEffect, useState } from 'react';
import { __ } from '@wordpress/i18n';
import { api } from '../api';
import { Button, Badge, Notice, Segmented } from './ui';
import { IconSparkle } from './icons';

/**
 * The per-page AI tools that used to be routing entries with no caller:
 * passage rewrites, a schema proposal, alt text, internal links, translation.
 *
 * Same contract as the title/description card: every tool proposes, shows the
 * receipt (model, tokens, cost), and only an explicit Apply writes — one item
 * at a time, so a reviewer can take three of five rewrites and leave two.
 * Content-changing applies keep a snapshot in the page's AI history for undo.
 */

const Receipt = ({ r }) =>
	r && r.model ? (
		<span className="t-caption">
			{r.provider} · {r.model} · {(r.prompt_tokens || 0) + (r.completion_tokens || 0)} {__('tokens', 'ai-rank-suite')} · {r.cost} · {r.latency_ms} ms
		</span>
	) : null;

function useRun() {
	const [busy, setBusy] = useState('');
	const [error, setError] = useState(null);
	const run = async (name, fn) => {
		setBusy(name);
		setError(null);
		try {
			return await fn();
		} catch (e) {
			setError(e.message);
			return null;
		} finally {
			setBusy('');
		}
	};
	return { busy, error, run, setError };
}

/* ---------- Rewrite ---------- */
function Rewrite({ postId, onServerEdit }) {
	const { busy, error, run } = useRun();
	const [data, setData] = useState(null);
	const [focus, setFocus] = useState('');
	const [drafts, setDrafts] = useState({});
	const [applied, setApplied] = useState({});
	const [canUndo, setCanUndo] = useState(false);

	const propose = () =>
		run('propose', async () => {
			const r = await api.post(`/ai/rewrite/${postId}`, { focus });
			setData(r);
			setDrafts(Object.fromEntries((r.edits || []).map((e, i) => [i, e.rewritten])));
			setApplied({});
		});
	const apply = (i) =>
		run(`apply${i}`, async () => {
			const e = data.edits[i];
			await api.post(`/ai/rewrite/${postId}/apply`, { original: e.original, rewritten: drafts[i] });
			setApplied((a) => ({ ...a, [i]: true }));
			setCanUndo(true);
			// The body of the page just changed, so the word count, the scores
			// and every check are now about the previous version.
			if (onServerEdit) onServerEdit();
		});
	const undo = () =>
		run('undo', async () => {
			await api.post(`/ai/rewrite/${postId}/undo`, {});
			setCanUndo(false);
			setApplied({});
			if (onServerEdit) onServerEdit();
		});

	return (
		<div className="grid gap-3">
			<p className="m-0 text-[12.5px]" style={{ color: 'var(--ars-ink-2)' }}>
				{__('The AI picks the passages where a change most improves quotability or clarity and rewrites only those — no new facts, same language and register. Apply the ones you agree with; each apply is undoable.', 'ai-rank-suite')}
			</p>
			<div className="flex items-center gap-2 flex-wrap">
				<input type="text" placeholder={__('Optional focus, e.g. "answer the question in the first line"', 'ai-rank-suite')} value={focus} onChange={(e) => setFocus(e.target.value)} style={{ flex: '1 1 260px' }} />
				<Button onClick={propose} busy={busy === 'propose'}>
					<IconSparkle size={13} /> {data ? __('Propose again', 'ai-rank-suite') : __('Propose rewrites', 'ai-rank-suite')}
				</Button>
				{canUndo && (
					<Button variant="ghost" onClick={undo} busy={busy === 'undo'}>
						{__('Undo last apply', 'ai-rank-suite')}
					</Button>
				)}
			</div>
			{error && <Notice tone="serious">{error}</Notice>}
			{data && data.edits.length === 0 && <Notice tone="good">{__('The AI found nothing worth changing.', 'ai-rank-suite')}</Notice>}
			{data &&
				data.edits.map((e, i) => (
					<div key={i} className={`ars-review-field${applied[i] ? ' is-applied' : ''}`}>
						<div className="flex items-center justify-between gap-2 flex-wrap">
							<span className="flex items-center gap-2">
								<Badge tone="brand">{e.kind.replace('_', ' ')}</Badge>
								{typeof e.confidence === 'number' && <Badge tone={e.confidence >= 70 ? 'good' : 'warning'}>{e.confidence}%</Badge>}
								{!e.locatable && <Badge tone="warning">{__('passage not found verbatim — copy by hand', 'ai-rank-suite')}</Badge>}
								{applied[i] && <Badge tone="good">✓ {__('applied', 'ai-rank-suite')}</Badge>}
							</span>
							{e.locatable && !applied[i] && (
								<Button onClick={() => apply(i)} busy={busy === `apply${i}`}>
									{__('Apply this', 'ai-rank-suite')}
								</Button>
							)}
						</div>
						<div className="ars-review-orig">
							<span className="t-caption">{__('Now', 'ai-rank-suite')}:</span> {e.original}
						</div>
						<textarea rows={Math.min(8, Math.max(2, Math.ceil((drafts[i] || '').length / 90)))} value={drafts[i] || ''} onChange={(ev) => setDrafts({ ...drafts, [i]: ev.target.value })} disabled={!!applied[i]} />
						{e.reason && <div className="t-caption">{e.reason}</div>}
					</div>
				))}
			{data && (
				<div className="ars-review-meta">
					<Receipt r={data.receipt} />
					{data.chars_sent ? <span>{data.chars_sent.toLocaleString()} {__('chars sent', 'ai-rank-suite')}</span> : null}
					{data.redacted && Object.keys(data.redacted).length > 0 ? <span>{__('redacted', 'ai-rank-suite')}: {Object.entries(data.redacted).map(([k, v]) => `${v} ${k}`).join(', ')}</span> : null}
				</div>
			)}
		</div>
	);
}

/* ---------- Schema ---------- */
function SchemaTool({ postId, onApply }) {
	const { busy, error, run } = useRun();
	const [data, setData] = useState(null);
	const [fields, setFields] = useState({});
	const propose = () =>
		run('propose', async () => {
			const r = await api.post(`/ai/schema/${postId}`, {});
			setData(r);
			setFields(r.fields || {});
		});
	return (
		<div className="grid gap-3">
			<p className="m-0 text-[12.5px]" style={{ color: 'var(--ars-ink-2)' }}>
				{__('The AI proposes the best-fitting schema type this plugin supports and fills only fields whose values appear on the page — never a price, rating or date it did not read. You review, then hand it to the schema editor.', 'ai-rank-suite')}
			</p>
			<div>
				<Button onClick={propose} busy={busy === 'propose'}>
					<IconSparkle size={13} /> {data ? __('Propose again', 'ai-rank-suite') : __('Propose schema', 'ai-rank-suite')}
				</Button>
			</div>
			{error && <Notice tone="serious">{error}</Notice>}
			{data && (
				<div className="ars-review-field">
					<div className="flex items-center gap-2 flex-wrap">
						<span className="font-semibold text-[13.5px]">{data.type}</span>
						<Badge tone={data.confidence >= 70 ? 'good' : 'warning'}>{data.confidence}% {__('confident', 'ai-rank-suite')}</Badge>
					</div>
					{data.why && <div className="t-caption">{data.why}</div>}
					{Object.keys(fields).length === 0 ? (
						<Notice tone="warning">{__('The page did not contain enough facts to fill any field. Add the details to the page, or fill the schema by hand.', 'ai-rank-suite')}</Notice>
					) : (
						<div className="grid gap-2 sm:grid-cols-2">
							{Object.entries(fields).map(([k, v]) => (
								<label key={k} className="grid gap-1 text-[12px]">
									<span className="t-caption">{data.labels?.[k] || k}</span>
									<input type="text" value={v} onChange={(e) => setFields({ ...fields, [k]: e.target.value })} />
								</label>
							))}
						</div>
					)}
					<div className="flex items-center gap-2 flex-wrap">
						<Button onClick={() => onApply && onApply({ type: data.type, data: fields })} disabled={Object.keys(fields).length === 0}>
							{__('Add to this page’s schema', 'ai-rank-suite')}
						</Button>
						<Receipt r={data.receipt} />
					</div>
				</div>
			)}
		</div>
	);
}

/* ---------- Alt text ---------- */
function AltTool({ postId, onServerEdit }) {
	const { busy, error, run } = useRun();
	const [images, setImages] = useState(null);
	const [data, setData] = useState(null);
	const [drafts, setDrafts] = useState({});
	const [done, setDone] = useState(0);
	useEffect(() => {
		api.get(`/ai/alt/${postId}`).then((r) => setImages(r.images || [])).catch(() => setImages([]));
	}, [postId]);
	const propose = () =>
		run('propose', async () => {
			const r = await api.post(`/ai/alt/${postId}`, {});
			setData(r);
			setDrafts(Object.fromEntries((r.alts || []).map((a) => [a.id, a.alt])));
		});
	const applyAll = () =>
		run('apply', async () => {
			const r = await api.post('/ai/alt/apply', { alts: Object.entries(drafts).map(([id, alt]) => ({ id: Number(id), alt })) });
			if (onServerEdit) onServerEdit();
			setDone(r.applied || 0);
			setImages([]);
		});
	if (images === null) return null;
	return (
		<div className="grid gap-3">
			<p className="m-0 text-[12.5px]" style={{ color: 'var(--ars-ink-2)' }}>
				{__('One plain sentence per image that has none, from the page context and file name — written into the media library, so every page that uses the image gets it.', 'ai-rank-suite')}
			</p>
			{images.length === 0 && !data ? (
				<Notice tone="good">{done ? `${done} ${__('alt texts written.', 'ai-rank-suite')}` : __('Every media-library image on this page already has alt text.', 'ai-rank-suite')}</Notice>
			) : (
				<div className="flex items-center gap-2 flex-wrap">
					<Badge tone="warning">{images.length} {__('images without alt text', 'ai-rank-suite')}</Badge>
					<Button onClick={propose} busy={busy === 'propose'}>
						<IconSparkle size={13} /> {__('Write alt text', 'ai-rank-suite')}
					</Button>
				</div>
			)}
			{error && <Notice tone="serious">{error}</Notice>}
			{data && data.alts.length > 0 && (
				<div className="grid gap-2">
					{data.alts.map((a) => (
						<div key={a.id} className="ars-alt-row">
							<img src={a.url} alt="" />
							<div className="grid gap-1 min-w-0">
								<span className="t-caption truncate">{a.file}</span>
								<input type="text" value={drafts[a.id] || ''} onChange={(e) => setDrafts({ ...drafts, [a.id]: e.target.value })} maxLength={160} />
								<span className="t-caption">{(drafts[a.id] || '').length}/125 {a.confidence < 60 ? `· ${__('low confidence — check', 'ai-rank-suite')}` : ''}</span>
							</div>
						</div>
					))}
					<div className="flex items-center gap-2 flex-wrap">
						<Button onClick={applyAll} busy={busy === 'apply'}>
							{__('Save all to media library', 'ai-rank-suite')}
						</Button>
						<Receipt r={data.receipt} />
					</div>
				</div>
			)}
		</div>
	);
}

/* ---------- Links ---------- */
function LinksTool({ postId, onServerEdit }) {
	const { busy, error, run } = useRun();
	const [data, setData] = useState(null);
	const [applied, setApplied] = useState({});
	const propose = () =>
		run('propose', async () => {
			setData(await api.post(`/ai/links/${postId}`, {}));
			setApplied({});
		});
	const apply = (i) =>
		run(`apply${i}`, async () => {
			const l = data.links[i];
			// The target travels as an id; the server builds the URL from it and
			// checks it against the suggestion table.
			await api.post(`/ai/links/${postId}/apply`, { anchor: l.anchor, target_id: l.target_id });
			// A new internal link is a change to the body, same as a rewrite.
			if (onServerEdit) onServerEdit();
			setApplied((a) => ({ ...a, [i]: true }));
		});
	return (
		<div className="grid gap-3">
			<p className="m-0 text-[12.5px]" style={{ color: 'var(--ars-ink-2)' }}>
				{__('The link module finds candidates locally; the AI reads this page and picks which of them a reader would actually want, with natural anchor text from a sentence already on the page. Same language only.', 'ai-rank-suite')}
			</p>
			<div>
				<Button onClick={propose} busy={busy === 'propose'}>
					<IconSparkle size={13} /> {data ? __('Propose again', 'ai-rank-suite') : __('Propose internal links', 'ai-rank-suite')}
				</Button>
			</div>
			{error && <Notice tone="serious">{error}</Notice>}
			{data && data.links.length === 0 && <Notice tone="warning">{__('None of the candidates fit this page well enough.', 'ai-rank-suite')}</Notice>}
			{data &&
				data.links.map((l, i) => (
					<div key={i} className="ars-review-field">
						<div className="flex items-center justify-between gap-2 flex-wrap">
							<span className="flex items-center gap-2 flex-wrap">
								<span className="font-semibold text-[13px]">→ {l.title}</span>
								{typeof l.confidence === 'number' && <Badge tone={l.confidence >= 70 ? 'good' : 'warning'}>{l.confidence}%</Badge>}
								{!l.locatable && <Badge tone="warning">{__('anchor not found verbatim', 'ai-rank-suite')}</Badge>}
								{applied[i] && <Badge tone="good">✓ {__('linked', 'ai-rank-suite')}</Badge>}
							</span>
							{l.locatable && !applied[i] && (
								<Button onClick={() => apply(i)} busy={busy === `apply${i}`}>
									{__('Insert link', 'ai-rank-suite')}
								</Button>
							)}
						</div>
						<div className="ars-review-orig">
							{__('Anchor', 'ai-rank-suite')}: <strong>{l.anchor}</strong> — <span className="t-caption">{l.passage}</span>
						</div>
						{l.reason && <div className="t-caption">{l.reason}</div>}
					</div>
				))}
			{data && <Receipt r={data.receipt} />}
		</div>
	);
}

/* ---------- Translate ---------- */
function TranslateTool({ postId, onUse }) {
	const { busy, error, run } = useRun();
	const [to, setTo] = useState('de');
	const [data, setData] = useState(null);
	const propose = () => run('propose', async () => setData(await api.post(`/ai/translate/${postId}`, { to })));
	return (
		<div className="grid gap-3">
			<p className="m-0 text-[12.5px]" style={{ color: 'var(--ars-ink-2)' }}>
				{__('Translate this page’s SEO title and description for its counterpart in another language, keeping brand words and length limits. Copy the result into the translated page.', 'ai-rank-suite')}
			</p>
			<div className="flex items-center gap-2 flex-wrap">
				<select value={to} onChange={(e) => setTo(e.target.value)}>
					{['en', 'de', 'ar', 'fr', 'es', 'it', 'nl', 'tr', 'ru', 'zh', 'ja', 'pt'].map((c) => (
						<option key={c} value={c}>
							{c}
						</option>
					))}
				</select>
				<Button onClick={propose} busy={busy === 'propose'}>
					<IconSparkle size={13} /> {__('Translate metadata', 'ai-rank-suite')}
				</Button>
			</div>
			{error && <Notice tone="serious">{error}</Notice>}
			{data && (
				<div className="ars-review-field" dir={['ar', 'he', 'fa', 'ur'].includes(data.to) ? 'rtl' : 'ltr'}>
					<div className="t-overline">{data.from} → {data.to}</div>
					<div className="font-semibold text-[13.5px]">{data.title}</div>
					<div className="text-[12.5px]">{data.description}</div>
					<div className="flex items-center gap-2 flex-wrap" dir="ltr">
						<Button variant="ghost" onClick={() => navigator.clipboard && navigator.clipboard.writeText(`${data.title}\n${data.description}`)}>
							{__('Copy', 'ai-rank-suite')}
						</Button>
						{onUse && (
							<Button variant="ghost" onClick={() => onUse(data)}>
								{__('Use on this page', 'ai-rank-suite')}
							</Button>
						)}
						<Receipt r={data.receipt} />
					</div>
				</div>
			)}
		</div>
	);
}

/**
 * `onServerEdit` — "this tool has already changed the page".
 *
 * Rewrite, Alt text and Links do not hand a draft back for the drawer to save;
 * they POST an /apply that writes to the database there and then. Nothing told
 * anybody, so the row in the list behind the drawer, its word count and its
 * scores all went on describing the page as it was before the edit, and the
 * drawer's own checks with them. The caller uses this to re-read the page.
 */
export default function AiTools({ postId, onSchema, onTranslate, onServerEdit }) {
	const [tab, setTab] = useState('rewrite');
	return (
		<div className="ars-review">
			<div className="ars-review-head">
				<span className="flex items-center gap-2 font-semibold text-[13px]">
					<IconSparkle size={14} /> {__('AI tools for this page', 'ai-rank-suite')}
				</span>
				<Segmented
					value={tab}
					onChange={setTab}
					options={[
						{ id: 'rewrite', label: __('Rewrite', 'ai-rank-suite') },
						{ id: 'schema', label: __('Schema', 'ai-rank-suite') },
						{ id: 'alt', label: __('Alt text', 'ai-rank-suite') },
						{ id: 'links', label: __('Links', 'ai-rank-suite') },
						{ id: 'translate', label: __('Translate', 'ai-rank-suite') },
					]}
				/>
			</div>
			{tab === 'rewrite' && <Rewrite postId={postId} onServerEdit={onServerEdit} />}
			{tab === 'schema' && <SchemaTool postId={postId} onApply={onSchema} />}
			{tab === 'alt' && <AltTool postId={postId} onServerEdit={onServerEdit} />}
			{tab === 'links' && <LinksTool postId={postId} onServerEdit={onServerEdit} />}
			{tab === 'translate' && <TranslateTool postId={postId} onUse={onTranslate} />}
		</div>
	);
}
