import React, { useEffect, useState } from 'react';
import { __, _n, sprintf } from '@wordpress/i18n';
import { api } from '../api';
import { Card, Button, Badge, Notice, Field, Switch, CodeBlock } from './ui';
import Explain from './Explain';

/**
 * Outgoing webhooks — the plugin's events, delivered to a URL.
 *
 * Every subscription is a URL, a set of events, a secret and a switch. The
 * secret signs each delivery (HMAC-SHA256 of the raw body, `X-AIRS-Signature`)
 * in the shape GitHub and Stripe use, so a Zapier, Make, n8n or hand-written
 * receiver verifies it the way it already knows. The last forty deliveries are
 * kept so "did it fire?" has an answer.
 */
export default function Webhooks() {
	const [data, setData] = useState(null);
	const [error, setError] = useState(null);
	const [form, setForm] = useState(null); // null = closed; {} = new; {id} = edit
	const [busy, setBusy] = useState('');
	const [minted, setMinted] = useState(null);
	const [testResult, setTestResult] = useState(null);

	const load = () => api.get('/webhooks').then(setData).catch((e) => setError(e.message));
	useEffect(() => {
		load();
	}, []);

	const run = async (name, fn) => {
		setBusy(name);
		setError(null);
		try {
			await fn();
		} catch (e) {
			setError(e.message);
		} finally {
			setBusy('');
		}
	};

	const save = () =>
		run('save', async () => {
			const r = await api.post('/webhooks', form);
			setData(r);
			if (r.saved?.minted) setMinted({ id: r.saved.id, secret: r.saved.minted });
			setForm(null);
		});
	const remove = (id) => run(`del-${id}`, async () => setData(await api.del(`/webhooks/${id}`)));
	const test = (id) =>
		run(`test-${id}`, async () => {
			const r = await api.post(`/webhooks/${id}/test`, {});
			setData(r);
			setTestResult({ id, ...r.result });
		});
	const toggle = (h) => run(`toggle-${h.id}`, async () => setData(await api.post('/webhooks', { id: h.id, url: h.url, events: h.events, label: h.label, active: !h.active })));

	if (!data) return null;

	const events = Object.entries(data.events || {});
	const hooks = data.hooks || [];
	const deliveries = data.deliveries || [];
	const hookLabel = (id) => hooks.find((h) => h.id === id)?.label || hooks.find((h) => h.id === id)?.url || id.slice(0, 8);

	return (
		<div className="grid gap-4">
			{error && <Notice tone="serious">{error}</Notice>}

			{minted && (
				<Notice tone="good">
					<div className="grid gap-1">
						<b>{__('Signing secret for this webhook — shown once, copy it now.', 'ai-rank-suite')}</b>
						<code className="ars-mono" style={{ wordBreak: 'break-all' }}>
							{minted.secret}
						</code>
						<span className="t-caption">{__('Verify each delivery:', 'ai-rank-suite')}<code>sha256=HMAC_SHA256(raw_body, secret)</code> {__('must equal the', 'ai-rank-suite')}{' '}
							<code>{__('X-AIRS-Signature', 'ai-rank-suite')}</code> {__('header. To rotate, edit the webhook and enter a new secret.', 'ai-rank-suite')}
						</span>
						<button type="button" className="ars-linkbtn justify-self-start" onClick={() => setMinted(null)}>{__('I have copied it', 'ai-rank-suite')}</button>
					</div>
				</Notice>
			)}

			<Card
				title={__('Webhooks', 'ai-rank-suite')}
				subtitle={__('A signed POST to your URL when something happens here — Zapier, Make, n8n, Slack, your own dashboard', 'ai-rank-suite')}
				action={
					!form && (
						<Button onClick={() => setForm({ url: '', label: '', events: ['audit.finished', 'score.recalculated'], secret: '', active: true })}>{__('Add webhook', 'ai-rank-suite')}</Button>
					)
				}
				flush
			>
				{form && (
					<div className="px-4 py-4 grid gap-3" style={{ borderBottom: '1px solid var(--ars-border)', background: 'var(--ars-surface-2)' }}>
						<div className="grid gap-3 md:grid-cols-[minmax(0,1fr)_240px]">
							<Field label={__('Endpoint URL', 'ai-rank-suite')} hint={__('Public https URL. Private and local addresses are refused.', 'ai-rank-suite')}>
								<input type="url" value={form.url} onChange={(e) => setForm({ ...form, url: e.target.value })} placeholder="https://hooks.zapier.com/hooks/catch/…" style={{ width: '100%' }} />
							</Field>
							<Field label={__('Label', 'ai-rank-suite')} hint={__('For the list only.', 'ai-rank-suite')}>
								<input type="text" value={form.label} onChange={(e) => setForm({ ...form, label: e.target.value })} placeholder={__('Slack #seo', 'ai-rank-suite')} style={{ width: '100%' }} />
							</Field>
						</div>
						<Field label={__('Events', 'ai-rank-suite')} hint={__('Which of the plugin\'s events this URL receives.', 'ai-rank-suite')}>
							<div className="ars-eventgrid">
								{events.map(([key, ev]) => {
									const on = form.events.includes(key);
									return (
										<label key={key} className={`ars-event${on ? ' is-on' : ''}`}>
											<input
												type="checkbox"
												checked={on}
												onChange={() => setForm({ ...form, events: on ? form.events.filter((x) => x !== key) : [...form.events, key] })}
											/>
											<span className="grid gap-0.5 min-w-0">
												<span className="font-semibold text-[12.5px]">{ev.label}</span>
												<span className="t-caption">{ev.detail}</span>
												<code className="ars-mono t-caption">{key}</code>
											</span>
										</label>
									);
								})}
							</div>
						</Field>
						<Field label={__('Signing secret', 'ai-rank-suite')} hint={form.id ? __('Leave empty to keep the current secret; enter a new one to rotate it.', 'ai-rank-suite') : __('Leave empty and one is generated for you — shown once after saving.', 'ai-rank-suite')}>
							<input type="password" autoComplete="off" value={form.secret} onChange={(e) => setForm({ ...form, secret: e.target.value })} placeholder={__('optional', 'ai-rank-suite')} style={{ maxWidth: 360 }} />
						</Field>
						<div className="flex items-center gap-2">
							<Button onClick={save} busy={busy === 'save'} disabled={!form.url.trim() || form.events.length === 0}>
								{form.id ? __('Save changes', 'ai-rank-suite') : __('Create webhook', 'ai-rank-suite')}
							</Button>
							<Button variant="ghost" onClick={() => setForm(null)}>{__('Cancel', 'ai-rank-suite')}</Button>
						</div>
					</div>
				)}

				{hooks.length === 0 && !form ? (
					<div className="px-4 py-5 grid gap-2">
						<span className="font-medium text-[13px]">{__('No webhooks yet.', 'ai-rank-suite')}</span>
						<span className="text-[12.5px]" style={{ color: 'var(--ars-ink-2)' }}>{__('Add one and the plugin will POST a signed JSON envelope —', 'ai-rank-suite')}<code>event</code>, <code>site</code>,{' '}
							<code>time</code>, <code>data</code> {__('— to that URL whenever a selected event happens.', 'ai-rank-suite')}
						</span>
					</div>
				) : (
					<div className="ars-table-wrap">
						<table className="ars-table">
							<thead>
								<tr>
									<th>{__('Endpoint', 'ai-rank-suite')}</th>
									<th>{__('Events', 'ai-rank-suite')}</th>
									<th>{__('Last delivery', 'ai-rank-suite')}</th>
									<th style={{ width: 230 }} />
								</tr>
							</thead>
							<tbody>
								{hooks.map((h) => (
									<tr key={h.id} style={{ opacity: h.active ? 1 : 0.6 }}>
										<td>
											<div className="grid gap-0.5" style={{ maxWidth: 380 }}>
												<span className="font-semibold text-[13px] truncate">{h.label || h.url}</span>
												{h.label && <span className="ars-mono t-caption truncate">{h.url}</span>}
											</div>
										</td>
										<td>
											<span className="flex flex-wrap gap-1">
												{h.events.map((ev) => (
													<Badge key={ev} tone="neutral">
														{ev}
													</Badge>
												))}
											</span>
										</td>
										<td>
											{h.last ? (
												<span className="grid gap-0.5">
													<Badge tone={h.last_ok ? 'good' : 'serious'}>{h.last_ok ? sprintf(__('%s ok', 'ai-rank-suite'), h.last_status) : h.last_status ? `HTTP ${h.last_status}` : __('unreachable', 'ai-rank-suite')}</Badge>
													<span className="t-caption">
														{new Date(h.last * 1000).toLocaleString()}
														{h.failures > 1 ? ` · ${sprintf(_n('%d failure in a row', '%d failures in a row', h.failures, 'ai-rank-suite'), h.failures)}` : ''}
													</span>
												</span>
											) : (
												<span className="t-caption">{__('never', 'ai-rank-suite')}</span>
											)}
										</td>
										<td>
											<div className="ars-actions">
												<Switch checked={!!h.active} onChange={() => toggle(h)} label="" />
												<Button variant="ghost" busy={busy === `test-${h.id}`} onClick={() => test(h.id)}>{__('Test', 'ai-rank-suite')}</Button>
												<Button variant="ghost" onClick={() => setForm({ id: h.id, url: h.url, label: h.label || '', events: h.events, secret: '', active: h.active })}>{__('Edit', 'ai-rank-suite')}</Button>
												<Button variant="ghost" busy={busy === `del-${h.id}`} onClick={() => remove(h.id)}>{__('Delete', 'ai-rank-suite')}</Button>
											</div>
										</td>
									</tr>
								))}
							</tbody>
						</table>
					</div>
				)}
				{testResult && (
					<p className="m-0 px-4 py-2 t-caption">
						{sprintf(__('Test to %s:', 'ai-rank-suite'), hookLabel(testResult.id))} {testResult.ok ? sprintf(__('delivered, HTTP %1$s in %2$s ms', 'ai-rank-suite'), testResult.status, testResult.ms) : sprintf(__('failed — %s', 'ai-rank-suite'), testResult.error || `HTTP ${testResult.status}`)}
					</p>
				)}
			</Card>

			<div className="grid gap-4 lg:grid-cols-2 items-stretch">
				<Card title={__('Recent deliveries', 'ai-rank-suite')} subtitle={__('The last forty, newest first', 'ai-rank-suite')} flush>
					{deliveries.length === 0 ? (
						<div className="px-4 py-4 t-caption">{__('Nothing delivered yet — press Test on a webhook.', 'ai-rank-suite')}</div>
					) : (
						<div className="ars-table-wrap">
							<table className="ars-table">
								<thead>
									<tr>
										<th>{__('When', 'ai-rank-suite')}</th>
										<th>{__('Event', 'ai-rank-suite')}</th>
										<th>{__('To', 'ai-rank-suite')}</th>
										<th className="is-num">{__('Result', 'ai-rank-suite')}</th>
									</tr>
								</thead>
								<tbody>
									{deliveries.slice(0, 20).map((d, i) => (
										<tr key={i}>
											<td className="is-muted" style={{ whiteSpace: 'nowrap' }}>
												{new Date(d.time * 1000).toLocaleString()}
											</td>
											<td>
												<code className="ars-mono text-[12px]">{d.event}</code>
											</td>
											<td className="truncate" style={{ maxWidth: 160 }}>
												{hookLabel(d.hook)}
											</td>
											<td className="is-num">
												<Badge tone={d.ok ? 'good' : 'serious'} title={d.error || ''}>
													{d.ok ? `${d.status} · ${d.ms} ms` : d.status ? `HTTP ${d.status}` : __('unreachable', 'ai-rank-suite')}
												</Badge>
											</td>
										</tr>
									))}
								</tbody>
							</table>
						</div>
					)}
				</Card>

				<Card title={__('Receiving a delivery', 'ai-rank-suite')} subtitle={__('The envelope, the headers, and how to verify the signature', 'ai-rank-suite')}>
					<div className="grid gap-3">
						<CodeBlock
							code={`POST ${'{your URL}'}
Content-Type: application/json
X-AIRS-Event: audit.finished
X-AIRS-Delivery: 8b1e…            (unique per delivery)
X-AIRS-Signature: sha256=…         (HMAC-SHA256 of the raw body)

{
  "event": "audit.finished",
  "site": "https://example.com/",
  "time": 1786990000,
  "version": "${(window.airanksuiteData || {}).version || ''}",
  "data": { "run_id": "…", "score": 74, "totals": { "critical": 0, "warning": 12, "notice": 3 } }
}`}
						/>
						<Explain title={__('Verify in PHP, Node or n8n', 'ai-rank-suite')}>
							<p>
								<code>hash_equals('sha256=' . hash_hmac('sha256', $rawBody, $secret), $_SERVER['HTTP_X_AIRANKSUITE_SIGNATURE'])</code>
								{' '}{__('— the same in Node with', 'ai-rank-suite')} <code>crypto.createHmac('sha256', secret).update(rawBody).digest('hex')</code>. {__('In n8n or Make, add a Crypto/HMAC step on the raw body and compare with the header. Reject anything that does not match; a 2xx from your side marks the delivery as ok here.', 'ai-rank-suite')}
							</p>
						</Explain>
						<p className="m-0 t-caption">{__('On the same install, no HTTP is needed:', 'ai-rank-suite')}<code>add_action('airanksuite/event', fn($name, $envelope) =&gt; …)</code> {__('or', 'ai-rank-suite')}{' '}
							<code>add_action('airanksuite/event/audit.finished', …)</code> {__('receive every event as a PHP action.', 'ai-rank-suite')}
						</p>
					</div>
				</Card>
			</div>
		</div>
	);
}
