import { useState } from "react";
import type { Change } from "../api/types";
import { WrapIcon } from "./icons";

function DiffView({ content, wrap }: { content: string; wrap: boolean }) {
	const lines = content.split("\n");
	return (
		<pre
			className={`scroll-x rounded-lg border border-border bg-bg p-2.5 text-[11px] leading-relaxed sm:p-3 sm:text-xs ${
				wrap ? "overflow-x-hidden" : ""
			}`}
		>
			<code>
				{lines.map((line, i) => {
					let cls = "";
					if (line.startsWith("+++") || line.startsWith("---")) cls = "diff-meta";
					else if (line.startsWith("@@")) cls = "diff-hunk";
					else if (line.startsWith("+")) cls = "diff-add";
					else if (line.startsWith("-")) cls = "diff-del";
					else if (line.startsWith("diff ") || line.startsWith("index ")) cls = "diff-meta";
					return (
						<div
							key={i}
							className={`px-1 ${wrap ? "whitespace-pre-wrap break-words" : "whitespace-pre"} ${cls}`}
						>
							{line || " "}
						</div>
					);
				})}
			</code>
		</pre>
	);
}

function fmtValue(v: unknown): string {
	if (v === null || v === undefined) return "∅";
	if (typeof v === "object") return JSON.stringify(v);
	return String(v);
}

function percentDelta(before: unknown, after: unknown): string | null {
	const b = Number(before);
	const a = Number(after);
	if (!Number.isFinite(b) || !Number.isFinite(a) || b === 0) return null;
	const pct = Math.round(((a - b) / Math.abs(b)) * 100);
	if (pct === 0) return null;
	return `${pct > 0 ? "+" : ""}${pct}%`;
}

function BeforeAfter({
	before,
	after,
	contentType,
}: {
	before: unknown;
	after: unknown;
	contentType?: string | null;
}) {
	const delta = contentType === "integer" || contentType === "number" ? percentDelta(before, after) : null;
	return (
		<div className="flex flex-wrap items-center gap-x-2 gap-y-1.5 text-sm">
			<code className="diff-del max-w-full break-all rounded px-2 py-0.5 font-mono">{fmtValue(before)}</code>
			<span className="text-faint">→</span>
			<code className="diff-add max-w-full break-all rounded px-2 py-0.5 font-mono">{fmtValue(after)}</code>
			{delta && <span className="rounded bg-primary-dim/40 px-2 py-0.5 text-xs text-primary">{delta}</span>}
			{contentType && <span className="text-xs text-faint">({contentType})</span>}
		</div>
	);
}

function typeChip(label: string, color: string) {
	return <span className={`shrink-0 rounded px-2 py-0.5 text-xs font-medium ${color}`}>{label}</span>;
}

export function ChangeCard({ change, index }: { change: Change; index: number }) {
	const [wrap, setWrap] = useState(false);

	return (
		<div className="rounded-xl border border-border bg-surface-raised/50 p-3 sm:p-4">
			<div className="mb-3 flex items-start gap-2">
				<span className="mt-0.5 shrink-0 font-mono text-xs text-faint">#{index + 1}</span>

				<div className="flex min-w-0 flex-1 flex-wrap items-center gap-x-2 gap-y-1.5">
					{change.type === "unified_diff" && (
						<>
							{typeChip("diff", "bg-primary-dim/40 text-primary")}
							<code className="min-w-0 break-all text-sm text-text">{change.path}</code>
						</>
					)}
					{change.type === "config" && (
						<>
							{typeChip("config", "bg-accent/15 text-accent")}
							<code className="min-w-0 break-all text-sm text-text">{change.path}</code>
						</>
					)}
					{change.type === "custom" && (
						<>
							{typeChip("custom", "bg-changes/15 text-changes")}
							<span className="min-w-0 break-words text-sm text-text">{change.label}</span>
						</>
					)}
				</div>

				{/* Wrapping beats horizontal scrolling for long lines on a phone. */}
				{change.type === "unified_diff" && (
					<button
						onClick={() => setWrap((w) => !w)}
						aria-pressed={wrap}
						title={wrap ? "Disable line wrapping" : "Wrap long lines"}
						className={`tap-sm -mr-1 -mt-1 flex h-9 w-9 shrink-0 items-center justify-center rounded-lg transition ${
							wrap ? "bg-primary/15 text-primary" : "text-faint hover:bg-surface-raised hover:text-muted"
						}`}
					>
						<WrapIcon className="h-[18px] w-[18px]" />
					</button>
				)}
			</div>

			{change.type === "unified_diff" && <DiffView content={change.content} wrap={wrap} />}
			{change.type === "config" && (
				<BeforeAfter before={change.before} after={change.after} contentType={change.content_type} />
			)}
			{change.type === "custom" && <BeforeAfter before={change.before} after={change.after} />}
		</div>
	);
}

export function ChangeList({ changes }: { changes: Change[] }) {
	return (
		<div className="space-y-3">
			{changes.map((c, i) => (
				<ChangeCard key={i} change={c} index={i} />
			))}
		</div>
	);
}
