import {
	ExternalLink,
	Unlink,
	FileText,
	ArrowLeft,
	Check,
	Loader2,
} from 'lucide-react';
import { Button } from '@/components/ui/button';
import FlavioIcon from '@/components/ui/flavio-icon';
import { isAppPaused } from '@/api/client';
import { useInterventionResponse } from '@/features/interventions/useInterventionResponse';
import UpgradeLock from '@/features/interventions/detail/UpgradeLock';

/**
 * Detail for the `no404` / `broken_links` intervention (type `help`).
 *
 * A broken link points to a page that no longer exists (404). Flavio knows which
 * links are broken and on which pages, but it can't know what each one *should*
 * point to, so the fix is the user's: update or remove the link in the page
 * content. The steps are instructional. The scan re-checks the links on its next
 * cycle and the heartbeat auto-resolves the ones that respond again, but that can
 * lag, so we also give the user an explicit "I've already done this" action that
 * acknowledges the intervention (`status: 'acknowledge'`) and clears it now.
 *
 * The scanner payload (`no404` is pass-through) is two levels deep:
 *   pending_items: [{ type:"page", url, title, pending_count, pending_items:[
 *                     { type:"link", url, total_count } ] }]
 * The outer level is the *page to edit* (the actionable bit), the inner level its
 * broken links. We group the UI the same way so the user knows where each one is.
 *
 * Defensive on metadata: the base contract only guarantees `variant`, so every
 * field below is read with a fallback.
 */

/** What the user does with each broken link (the fix lives in their content). */
const STEPS = [
	{
		text: 'Open each page and find the link.',
		hint: 'I list the broken links under each page above.',
	},
	{ text: 'Update it to the right URL, or remove it if that page is gone.' },
	{ text: "I'll confirm each fix on my next check." },
];

/** Normalise an inner scanner item (a broken link) to `{ url, count }`. */
const normalizeLink = (link) => ({
	url: typeof link === 'string' ? link : link?.url || '',
	count: Number(typeof link === 'string' ? 0 : link?.total_count) || 0,
});

/** Normalise an outer scanner item (a page) to `{ url, title, links, count }`. */
const normalizePage = (page) => {
	if (typeof page === 'string') {
		return { url: page, title: '', links: [], count: 0 };
	}
	const links = (Array.isArray(page?.pending_items) ? page.pending_items : [])
		.map(normalizeLink)
		.filter((link) => link.url);
	return {
		url: page?.url || '',
		title: page?.title || '',
		links,
		count: Number(page?.pending_count) || links.length,
	};
};

const MAX_PAGES = 6;
const MAX_LINKS = 5;

const BrokenLinks = ({
	intervention = {},
	interventionId,
	onBack,
	onResolved,
}) => {
	const metadata = intervention.metadata || {};
	const pages = (
		Array.isArray(metadata.pending_items) ? metadata.pending_items : []
	)
		.map(normalizePage)
		.filter((page) => page.url || page.links.length);

	const pageCount = Number(metadata.pending_count) || pages.length;
	const linkCount = pages.reduce((sum, page) => sum + page.count, 0);

	const shownPages = pages.slice(0, MAX_PAGES);
	const morePages = Math.max(pageCount - shownPages.length, 0);

	const summary = linkCount
		? `I found ${linkCount} broken ${linkCount === 1 ? 'link' : 'links'}${
				pageCount > 1 ? ` across ${pageCount} pages` : ''
			}. `
		: '';
	const deadEnd =
		linkCount === 1
			? 'It points to a page that no longer exists, so visitors hit a dead end.'
			: 'Each one points to a page that no longer exists, so visitors hit a dead end.';
	const action = linkCount === 1 ? 'Update or remove it' : 'Update or remove them';

	// Trial ended: the intervention can't be acted on, so its action buttons are
	// swapped for the single "unlock" upgrade CTA.
	const isPaused = isAppPaused();

	const { pending, resolved, error, run } = useInterventionResponse(
		interventionId,
		{ onResolved }
	);

	if (resolved) {
		return (
			<div className="max-w-2xl mx-auto text-center">
				<FlavioIcon className="w-12 h-12 mx-auto mb-4" />
				<h1 className="heading-h2 mt-0! leading-tight mb-3">Got it</h1>
				<div className="max-w-md mx-auto">
					<p className="paragraph-regular text-muted-foreground mb-0!">
						Thanks. I'll re-check those links and pick things up from
						there.
					</p>
				</div>
				{onBack && (
					<Button
						onClick={onBack}
						size="lg"
						className="mt-6 bg-foreground text-background! hover:bg-foreground/90"
					>
						<ArrowLeft />
						Back to your list
					</Button>
				)}
			</div>
		);
	}

	return (
		<div className="max-w-2xl mx-auto text-center">
			<h1 className="heading-h1 mt-0! leading-tight mb-3">
				{linkCount === 1
					? 'A link on your site is broken'
					: 'Some links on your site are broken'}
			</h1>
			<div className="max-w-xl mx-auto mb-8">
				<p className="paragraph-regular text-muted-foreground mb-0!">
					{summary}
					{deadEnd} {action} to keep your site tidy for search.
				</p>
			</div>

			{shownPages.length > 0 && (
				<div className="rounded-2xl border border-border p-6 text-left">
					<h2 className="heading-h4 mt-0! mb-4">Where to fix them</h2>
					<ul className="divide-y divide-border mt-4">
						{shownPages.map((page, pageIndex) => {
							const shownLinks = page.links.slice(0, MAX_LINKS);
							const moreLinks = Math.max(
								page.count - shownLinks.length,
								0
							);

							return (
								<li
									key={`${page.url}-${pageIndex}`}
									className="py-4 first:pt-0 last:pb-0"
								>
									{page.url ? (
										<a
											href={page.url}
											target="_blank"
											rel="noopener noreferrer"
											className="inline-flex max-w-full items-center gap-1.5 small-semibold text-foreground! hover:underline"
										>
											<FileText className="w-4 h-4 shrink-0 text-muted-foreground" />
											<span className="truncate">
												{page.title || page.url} {page.title && page.url && (
													<span className="small-regular text-muted-foreground truncate my-0! mt-0.5!">
														({page.url})
													</span>
												)}
											</span>
											<ExternalLink className="w-3.5 h-3.5 shrink-0 text-muted-foreground" />
										</a>
									) : (
										<span className="small-semibold text-foreground">
											{page.title} {page.title && page.url && (
										<span className="small-regular text-muted-foreground truncate my-0! mt-0.5!">
											({page.url})
										</span>
									)}
										</span>
									)}
									

									{shownLinks.length > 0 && (
										<ul className="mt-2 space-y-1.5 pl-[1.375rem]">
											{shownLinks.map((link, linkIndex) => (
												<li
													key={`${link.url}-${linkIndex}`}
													className="flex items-center gap-2 small-regular text-muted-foreground"
												>
													<Unlink className="w-3.5 h-3.5 shrink-0 text-amber-600" />
													<span className="truncate">
														{link.url}
													</span>
													{link.count > 1 && (
														<span className="shrink-0 text-muted-foreground/70">
															×{link.count}
														</span>
													)}
												</li>
											))}
											{moreLinks > 0 && (
												<li className="small-regular text-muted-foreground/70">
													and {moreLinks} more on this page
												</li>
											)}
										</ul>
									)}
								</li>
							);
						})}
					</ul>
					{morePages > 0 && (
						<p className="small-regular text-muted-foreground mt-4 mb-0!">
							and {morePages} more page{morePages === 1 ? '' : 's'}
						</p>
					)}
				</div>
			)}

			<div className="rounded-2xl border border-border p-8 mt-4">
				<h2 className="heading-h4 mt-0! mb-6">How to fix them</h2>
				<div className="space-y-5 text-left mt-4">
					{STEPS.map((step, index) => (
						<div key={step.text} className="flex items-start gap-4">
							<span className="flex items-center justify-center w-8 h-8 rounded-full border border-border text-muted-foreground small-semibold shrink-0">
								{index + 1}
							</span>
							<div>
								<p className="paragraph-regular text-foreground my-0! pt-0.5">
									{step.text}
								</p>
								{step.hint && (
									<p className="small-regular text-muted-foreground mt-1! mb-0!">
										{step.hint}
									</p>
								)}
							</div>
						</div>
					))}
				</div>
			</div>

			<div className="max-w-xl mx-auto mt-6 flex items-start justify-center gap-2 small-regular text-muted-foreground">
				<Unlink className="w-4 h-4 shrink-0 mt-0.5" />
				<span className="text-left">
					Every broken link is a dead end for visitors and a wasted stop
					for search engines.
				</span>
			</div>

			{isPaused ? (
				<div className="mt-8">
					<UpgradeLock />
				</div>
			) : (
				/* Already-done escape hatch: acknowledge so it clears now, without
				    waiting for the scan to re-check the links. */
				<div className="mt-8">
					<p className="small-regular text-muted-foreground my-0!">
						Already sorted this out? Let me know and I'll take it from
						here.
					</p>
					<Button
						onClick={() =>
							run('primary', {
								status: 'acknowledge',
								userResponse: { choice: 'already_done' },
							})
						}
						disabled={!!pending || !!resolved}
						variant="outline"
						size="lg"
						className="mt-4"
					>
						{pending === 'primary' ? (
							<Loader2 className="animate-spin" />
						) : (
							<Check />
						)}
						I've already done this
					</Button>

					{error && (
						<p className="small-regular text-destructive mt-3 mb-0!">
							{error}
						</p>
					)}
				</div>
			)}
		</div>
	);
};

export default BrokenLinks;
