import { useEffect, useState } from "react";
import { Button } from "~/shared/components/ui/button";
import { Input } from "~/shared/components/ui/input";
import { api } from "~/shared/lib/api";

interface MqttStatus {
	status: "connected" | "disconnected" | "error" | "not_configured";
	error: string | null;
}

interface TestResult {
	connected: boolean;
	receivedMessage: boolean;
	error?: string;
	samplePayload?: string;
}

interface WebhookPluginInfo {
	ok: boolean;
	installed?: boolean;
	plugin?: { Name?: string; Version?: string } | null;
	error?: string;
}

const HANDLEBARS_TEMPLATE = `{
  "event": "{{NotificationType}}",
  "itemId": "{{ItemId}}",
  "itemType": "{{ItemType}}"
}`;

function CopyableValue({ label, value, mono = true }: { label: string; value: string; mono?: boolean }) {
	const [copied, setCopied] = useState(false);
	const copy = async () => {
		await navigator.clipboard.writeText(value);
		setCopied(true);
		setTimeout(() => setCopied(false), 1500);
	};
	return (
		<div className="flex items-start gap-2 mb-2">
			<div className="text-xs text-gray-500 w-24 flex-shrink-0 pt-1.5">{label}</div>
			<pre className={`flex-1 text-xs bg-gray-50 border rounded px-2 py-1.5 overflow-x-auto ${mono ? "font-mono" : ""}`}>
				{value}
			</pre>
			<button
				type="button"
				onClick={copy}
				className="text-xs px-2 py-1 rounded border border-gray-300 text-gray-600 hover:bg-gray-100 flex-shrink-0"
			>
				{copied ? "Copied" : "Copy"}
			</button>
		</div>
	);
}

export function MqttSection({ cfg, locked }: { cfg: Record<string, string>; locked: Set<string> }) {
	const [url, setUrl] = useState(cfg.mqtt_url ?? "");
	const [topic, setTopic] = useState(cfg.mqtt_topic || "jellyfin/events");
	const [username, setUsername] = useState(cfg.mqtt_username ?? "");
	const [password, setPassword] = useState("");
	const [saving, setSaving] = useState(false);
	const [savedMsg, setSavedMsg] = useState("");
	const [testing, setTesting] = useState(false);
	const [testResult, setTestResult] = useState<TestResult | null>(null);
	const [status, setStatus] = useState<MqttStatus>({ status: "not_configured", error: null });
	const [plugin, setPlugin] = useState<WebhookPluginInfo | null>(null);

	const allLocked =
		locked.has("mqtt_url") && locked.has("mqtt_topic") && locked.has("mqtt_username") && locked.has("mqtt_password");

	useEffect(() => {
		let cancelled = false;
		const fetchStatus = async () => {
			try {
				const s = await api.get<MqttStatus>("/api/settings/mqtt/status");
				if (!cancelled) setStatus(s);
			} catch {
				/* ignore */
			}
		};
		fetchStatus();
		const interval = setInterval(fetchStatus, 5000);
		return () => {
			cancelled = true;
			clearInterval(interval);
		};
	}, []);

	useEffect(() => {
		api
			.get<WebhookPluginInfo>("/api/settings/jellyfin/webhook-plugin")
			.then(setPlugin)
			.catch((err) => setPlugin({ ok: false, error: String(err) }));
	}, []);

	const save = async () => {
		setSaving(true);
		setSavedMsg("");
		try {
			await api.post("/api/settings/mqtt", { url, topic, username, password });
			setSavedMsg(password ? "Saved." : "Saved (password unchanged).");
			setPassword("");
			setTimeout(() => setSavedMsg(""), 2500);
		} catch (e) {
			setSavedMsg(`Failed: ${String(e)}`);
		}
		setSaving(false);
	};

	const runTest = async () => {
		setTesting(true);
		setTestResult(null);
		try {
			const r = await api.post<TestResult>("/api/settings/mqtt/test", { url, topic, username, password });
			setTestResult(r);
		} catch (e) {
			setTestResult({ connected: false, receivedMessage: false, error: String(e) });
		}
		setTesting(false);
	};

	const statusColor =
		status.status === "connected"
			? "text-green-700 bg-green-50 border-green-300"
			: status.status === "error"
				? "text-red-700 bg-red-50 border-red-300"
				: status.status === "disconnected"
					? "text-amber-700 bg-amber-50 border-amber-300"
					: "text-gray-600 bg-gray-50 border-gray-300";

	return (
		<div className="border border-gray-200 rounded-lg p-4 mb-4">
			<div className="flex items-center justify-between mb-1">
				<div className="font-semibold text-sm">
					Jellyfin webhook <span className="text-gray-400 font-normal">(MQTT)</span>
				</div>
				<span className={`text-xs px-2 py-0.5 rounded border ${statusColor}`}>MQTT: {status.status}</span>
			</div>
			<p className="text-gray-500 text-sm mb-3 mt-0">
				Close the loop: once Jellyfin finishes its post-ffmpeg rescan, it publishes an event to your MQTT broker. We
				re-analyze the item, confirming it as done or flipping it back to pending if something didn't stick.
			</p>

			<label className="block text-sm text-gray-700 mb-1">
				Broker URL
				<Input
					type="url"
					value={url}
					onChange={(e) => setUrl(e.target.value)}
					placeholder="mqtt://192.168.1.10:1883"
					disabled={locked.has("mqtt_url")}
					className="mt-0.5 max-w-sm"
				/>
			</label>
			<label className="block text-sm text-gray-700 mb-1 mt-3">
				Topic
				<Input
					value={topic}
					onChange={(e) => setTopic(e.target.value)}
					placeholder="jellyfin/events"
					disabled={locked.has("mqtt_topic")}
					className="mt-0.5 max-w-xs"
				/>
			</label>
			<div className="grid grid-cols-2 gap-3 mt-3 max-w-md">
				<label className="block text-sm text-gray-700">
					Username
					<Input
						value={username}
						onChange={(e) => setUsername(e.target.value)}
						placeholder="(optional)"
						disabled={locked.has("mqtt_username")}
						className="mt-0.5"
					/>
				</label>
				<label className="block text-sm text-gray-700">
					Password
					<Input
						type="password"
						value={password}
						onChange={(e) => setPassword(e.target.value)}
						placeholder={cfg.mqtt_password ? "(unchanged)" : "(optional)"}
						disabled={locked.has("mqtt_password")}
						className="mt-0.5"
					/>
				</label>
			</div>

			<div className="flex items-center gap-2 mt-3">
				<Button onClick={save} disabled={saving || allLocked}>
					{saving ? "Saving…" : "Save"}
				</Button>
				<Button variant="secondary" onClick={runTest} disabled={testing || !url}>
					{testing ? "Testing…" : "Test connection"}
				</Button>
				{savedMsg && <span className="text-sm text-green-700">✓ {savedMsg}</span>}
			</div>

			{testResult && (
				<div className="mt-3 text-sm">
					{testResult.connected && testResult.receivedMessage && (
						<div className="text-green-700">
							✓ Connected and received a message.
							{testResult.samplePayload && (
								<pre className="mt-1 text-xs bg-gray-50 border rounded px-2 py-1 font-mono">{testResult.samplePayload}</pre>
							)}
						</div>
					)}
					{testResult.connected && !testResult.receivedMessage && !testResult.error && (
						<div className="text-amber-700">
							⚠ Connected, but no traffic in the timeout window. Trigger a library scan in Jellyfin, then retry.
						</div>
					)}
					{testResult.error && <div className="text-red-700">✗ {testResult.error}</div>}
				</div>
			)}

			{/* Plugin + setup instructions */}
			<div className="mt-4 pt-4 border-t border-gray-200">
				<div className="text-sm font-medium mb-2">Jellyfin Webhook plugin</div>
				{plugin?.ok === false && <p className="text-xs text-red-600">Couldn't reach Jellyfin: {plugin.error}</p>}
				{plugin?.ok && !plugin.installed && (
					<p className="text-xs text-amber-700">
						⚠ The Webhook plugin is not installed on Jellyfin. Install it from{" "}
						<span className="font-mono">Jellyfin → Dashboard → Plugins → Catalog → Webhook</span>, restart Jellyfin, then
						configure an MQTT destination with the values below.
					</p>
				)}
				{plugin?.ok && plugin.installed && (
					<p className="text-xs text-green-700 mb-2">
						✓ Plugin detected{plugin.plugin?.Version ? ` (v${plugin.plugin.Version})` : ""}. Add an MQTT destination with:
					</p>
				)}
				<div className="mt-2">
					<CopyableValue label="Broker URL" value={url || "mqtt://broker:1883"} />
					<CopyableValue label="Topic" value={topic || "jellyfin/events"} />
					<CopyableValue label="Events" value="Item Added, Item Updated" mono={false} />
					<CopyableValue label="Item types" value="Movie, Episode" mono={false} />
					<CopyableValue label="Template" value={HANDLEBARS_TEMPLATE} />
				</div>
			</div>
		</div>
	);
}
