import { useCallback, useEffect, useState } from "react";
import {
	Alert,
	AlertDescription,
	type BlockEditorProps,
	Button,
	type ReactNode,
	Card,
	CardContent,
	CardDescription,
	CardHeader,
	CardTitle,
	Tabs,
	TabsContent,
	TabsList,
	TabsTrigger,
	Input,
	Label,
	Textarea,
	Switch,
	Select,
	SelectContent,
	SelectItem,
	SelectTrigger,
	SelectValue,
	Settings,
	Edit3,
	CheckCircle2,
	XCircle,
	Loader2,
	Key,
	AlertCircle,
	ExternalLink,
	RefreshCw,
	t,
} from "@block-ninja/ui";

type EventTypeSummary = {
	id: number;
	slug: string;
	title: string;
	lengthInMinutes: number;
};

function renderConnectedAccount(apiKeyConfigured: boolean | null, calcomUsername: string) {
	if (apiKeyConfigured === false) {
		return <p className="text-xs text-muted-foreground">{t("calcom.editor.connectedAs.noKey", "Configure the API key in plugin settings to connect an account.")}</p>;
	}
	if (calcomUsername) {
		return <p className="text-sm font-mono">{calcomUsername}</p>;
	}
	return <p className="text-xs text-muted-foreground">{t("calcom.editor.connectedAs.resolving", "Resolving account from API key…")}</p>;
}

function CalcomBlockEditor({ content, onChange }: BlockEditorProps) {
	const [activeTab, setActiveTab] = useState("config");
	const [apiKeyConfigured, setApiKeyConfigured] = useState<boolean | null>(null);
	const [calcomUsername, setCalcomUsername] = useState<string>("");
	const [eventTypes, setEventTypes] = useState<EventTypeSummary[]>([]);
	const [loadingEventTypes, setLoadingEventTypes] = useState(false);
	const [fetchFailed, setFetchFailed] = useState(false);
	const [retryCounter, setRetryCounter] = useState(0);

	const handleFieldChange = useCallback(
		(field: string, value: unknown) => {
			onChange({ ...content, [field]: value });
		},
		[content, onChange],
	);

	const getString = (field: string, defaultValue = "") => {
		return (content[field] as string) || defaultValue;
	};

	const getNumber = (field: string, defaultValue = 0) => {
		const val = content[field];
		if (typeof val === "number") return val;
		if (typeof val === "string") return parseInt(val, 10) || defaultValue;
		return defaultValue;
	};

	const getBool = (field: string, defaultValue = false) => {
		const val = content[field];
		if (typeof val === "boolean") return val;
		return defaultValue;
	};

	const eventTypeSlug = getString("eventTypeSlug");

	useEffect(() => {
		fetch(`/api/plugins/calcomblock/settings`)
			.then((r) => r.json())
			.then((d: { api_key_configured?: boolean; username?: string }) => {
				setApiKeyConfigured(!!d.api_key_configured);
				setCalcomUsername(d.username ?? "");
			})
			.catch(() => setApiKeyConfigured(false));
	}, []);

	// Stamp the resolved Cal.com username into block content so the public
	// render path (block.go BookingConfig.Username) keeps working without any
	// backend rewiring. Existing blocks with a stale username get refreshed
	// automatically the next time the editor opens.
	useEffect(() => {
		if (calcomUsername && content.username !== calcomUsername) {
			onChange({ ...content, username: calcomUsername });
		}
	}, [calcomUsername, content, onChange]);

	useEffect(() => {
		if (!apiKeyConfigured) {
			setEventTypes([]);
			setFetchFailed(false);
			return;
		}
		const timer = setTimeout(() => {
			setLoadingEventTypes(true);
			setFetchFailed(false);
			fetch(`/api/plugins/calcomblock/event-types?username=${encodeURIComponent(calcomUsername)}`)
				.then((r) => r.json())
				.then((d: { success?: boolean; event_types?: EventTypeSummary[] }) => {
					if (d.success) {
						setEventTypes(d.event_types ?? []);
					} else {
						setEventTypes([]);
						setFetchFailed(true);
					}
				})
				.catch(() => {
					setEventTypes([]);
					setFetchFailed(true);
				})
				.finally(() => setLoadingEventTypes(false));
		}, 300);
		return () => clearTimeout(timer);
	}, [apiKeyConfigured, calcomUsername, retryCounter]);

	const handleRetry = useCallback(() => {
		setRetryCounter((n) => n + 1);
	}, []);

	const selectPlaceholder = (() => {
		if (apiKeyConfigured === false) {
			return (
				<span className="inline-flex items-center gap-1.5 text-muted-foreground">
					<Key className="h-3 w-3" />
					{t("calcom.editor.eventType.placeholder.noApiKey", "Configure API key first")}
				</span>
			);
		}
		if (loadingEventTypes) {
			return (
				<span className="inline-flex items-center gap-1.5 text-muted-foreground">
					<Loader2 className="h-3 w-3 animate-spin" />
					{t("calcom.editor.eventType.placeholder.loading", "Loading…")}
				</span>
			);
		}
		if (!calcomUsername) {
			return (
				<span className="inline-flex items-center gap-1.5 text-muted-foreground">
					<Loader2 className="h-3 w-3 animate-spin" />
					{t("calcom.editor.eventType.placeholder.resolvingUser", "Resolving account…")}
				</span>
			);
		}
		if (eventTypes.length === 0) {
			return (
				<span className="inline-flex items-center gap-1.5 text-muted-foreground">
					<XCircle className="h-3 w-3" />
					{t("calcom.editor.eventType.placeholder.noEventTypes", "No event types found")}
				</span>
			);
		}
		return t("calcom.editor.eventType.placeholder.select", "Select event type");
	})();

	const apiKeyReady = apiKeyConfigured === true;
	const usernameReady = calcomUsername.length > 0;
	const eventTypeReady = eventTypeSlug.length > 0;
	const canOpenInCalcom = usernameReady && eventTypeReady;

	const renderStatusRow = (ok: boolean, label: string, action?: ReactNode) => (
		<div className="flex items-center gap-2 text-sm">
			{ok ?
				<CheckCircle2 className="h-4 w-4 text-primary" aria-hidden="true" />
			:	<XCircle className="h-4 w-4 text-destructive" aria-hidden="true" />}
			<span className={ok ? "text-foreground" : "text-muted-foreground"}>{label}</span>
			{action ?
				<span className="ml-auto">{action}</span>
			:	null}
		</div>
	);

	return (
		<div className="space-y-4">
			<Tabs value={activeTab} onValueChange={setActiveTab}>
				<TabsList className="grid w-full grid-cols-2">
					<TabsTrigger value="config" className="gap-2">
						<Settings className="h-4 w-4" />
						<span>{t("calcom.editor.tab.configuration", "Configuration")}</span>
					</TabsTrigger>
					<TabsTrigger value="content" className="gap-2">
						<Edit3 className="h-4 w-4" />
						<span>{t("calcom.editor.tab.content", "Content")}</span>
					</TabsTrigger>
				</TabsList>

				{/* Configuration Tab */}
				<TabsContent value="config" className="space-y-4 mt-4">
					{apiKeyConfigured === false && (
						<Alert>
							<AlertDescription>
								{t("calcom.editor.alert.apiKeyMissing.prefix", "Configure your Cal.com API key in")}{" "}
								<a href="/admin/plugins?plugin=calcomblock" className="text-primary hover:underline">
									{t("calcom.editor.alert.apiKeyMissing.linkLabel", "plugin settings")}
								</a>{" "}
								{t("calcom.editor.alert.apiKeyMissing.suffix", "to enable the event-type dropdown.")}
							</AlertDescription>
						</Alert>
					)}

					<Card>
						<CardHeader>
							<CardTitle className="text-base">{t("calcom.editor.section.config.title", "Cal.com Settings")}</CardTitle>
							<CardDescription>{t("calcom.editor.section.config.description", "Connect to your Cal.com account and select an event type")}</CardDescription>
						</CardHeader>
						<CardContent className="space-y-4">
							<div className="space-y-2">
								<Label>{t("calcom.editor.connectedAs.label", "Connected Account")}</Label>
								{renderConnectedAccount(apiKeyConfigured, calcomUsername)}
							</div>

							<div className="space-y-2">
								<Label htmlFor="eventTypeSlug">
									{t("calcom.editor.eventType.label", "Event Type")} <span className="text-destructive">*</span>
								</Label>
								{fetchFailed ?
									<>
										<div className="flex items-center gap-2">
											<Input
												id="eventTypeSlug"
												value={eventTypeSlug}
												onChange={(e) => handleFieldChange("eventTypeSlug", e.target.value)}
												placeholder={t("calcom.editor.eventType.fallbackPlaceholder", "30min")}
												className="flex-1"
											/>
											<Button
												type="button"
												size="sm"
												variant="outline"
												action="retry"
												entity="event-types"
												onClick={handleRetry}
												disabled={loadingEventTypes}
												aria-label={t("calcom.editor.eventType.retryAria", "Retry loading event types")}>
												<RefreshCw className={`h-4 w-4 ${loadingEventTypes ? "animate-spin" : ""}`} aria-hidden="true" />
												<span className="ml-1">{t("calcom.editor.eventType.retryLabel", "Retry")}</span>
											</Button>
										</div>
										<Alert variant="destructive">
											<AlertCircle className="h-4 w-4" aria-hidden="true" />
											<AlertDescription>{t("calcom.editor.eventType.fetchFailed", "Couldn't load event types from Cal.com. Enter the slug manually or retry.")}</AlertDescription>
										</Alert>
									</>
								:	<>
										<Select
											value={eventTypeSlug}
											onValueChange={(v) => handleFieldChange("eventTypeSlug", v)}
											disabled={loadingEventTypes || !apiKeyConfigured || eventTypes.length === 0}>
											<SelectTrigger aria-label={t("calcom.editor.eventType.label", "Event Type")}>
												<SelectValue placeholder={selectPlaceholder} />
											</SelectTrigger>
											<SelectContent>
												{eventTypes.map((et) => (
													<SelectItem key={et.id} value={et.slug}>
														{et.title}
														<span className="text-muted-foreground">
															{" "}
															({et.slug} · {et.lengthInMinutes}m)
														</span>
													</SelectItem>
												))}
											</SelectContent>
										</Select>
										<p className="text-xs text-muted-foreground">{t("calcom.editor.eventType.help", "Fetched from your Cal.com account")}</p>
									</>
								}
							</div>

							<div className="space-y-2">
								<Label htmlFor="weeksToShow">{t("calcom.editor.weeksToShow.label", "Weeks to Display")}</Label>
								<Select value={String(getNumber("weeksToShow", 2))} onValueChange={(v) => handleFieldChange("weeksToShow", parseInt(v, 10))}>
									<SelectTrigger aria-label={t("calcom.editor.weeksToShow.label", "Weeks to Display")}>
										<SelectValue placeholder={t("calcom.editor.weeksToShow.placeholder", "Select weeks")} />
									</SelectTrigger>
									<SelectContent>
										{[1, 2, 3, 4, 5, 6, 7, 8].map((n) => (
											<SelectItem key={n} value={String(n)}>
												{n} {n > 1 ? t("calcom.editor.weeksToShow.unitPlural", "weeks") : t("calcom.editor.weeksToShow.unitSingular", "week")}
											</SelectItem>
										))}
									</SelectContent>
								</Select>
								<p className="text-xs text-muted-foreground">{t("calcom.editor.weeksToShow.help", "How many weeks of dates to show in the calendar")}</p>
							</div>

							<div className="flex items-center justify-between rounded-lg border p-3">
								<div className="space-y-0.5">
									<Label>{t("calcom.editor.showTimezone.label", "Show Timezone Selector")}</Label>
									<p className="text-xs text-muted-foreground">
										{t("calcom.editor.showTimezone.help", "Show a label above the date grid indicating which timezone times are displayed in.")}
									</p>
								</div>
								<Switch
									checked={getBool("showTimezone", true)}
									onCheckedChange={(v) => handleFieldChange("showTimezone", v)}
									aria-label={t("calcom.editor.showTimezone.label", "Show Timezone Selector")}
								/>
							</div>
						</CardContent>
					</Card>

					<Card>
						<CardHeader>
							<CardTitle className="text-base">{t("calcom.editor.status.title", "Configuration status")}</CardTitle>
							<CardDescription>{t("calcom.editor.status.description", "Quick check of the values needed before this block renders bookings.")}</CardDescription>
						</CardHeader>
						<CardContent className="space-y-2">
							{renderStatusRow(
								apiKeyReady,
								t("calcom.editor.status.apiKey", "API key configured"),
								!apiKeyReady ?
									<a href="/admin/plugins?plugin=calcomblock" className="text-xs text-primary hover:underline">
										{t("calcom.editor.status.apiKey.configureLink", "Configure")}
									</a>
								:	null,
							)}
							{renderStatusRow(usernameReady, t("calcom.editor.status.username", "Account resolved"))}
							{renderStatusRow(eventTypeReady, t("calcom.editor.status.eventType", "Event type selected"))}
							<div className="flex items-center gap-2 text-sm">
								<span className="inline-flex h-4 w-4 items-center justify-center text-muted-foreground">·</span>
								<span className="text-muted-foreground">
									{t("calcom.editor.status.eventTypesAvailable", "{count} event types available").replace("{count}", String(eventTypes.length))}
								</span>
							</div>
							<div className="pt-2">
								<Button
									type="button"
									size="sm"
									variant="outline"
									action="open"
									entity="calcom-page"
									asChild={canOpenInCalcom}
									disabled={!canOpenInCalcom}
									aria-label={t("calcom.editor.status.openExternalAria", "Open Cal.com booking page in a new tab")}>
									{canOpenInCalcom ?
										<a href={`https://cal.com/${calcomUsername}/${eventTypeSlug}`} target="_blank" rel="noopener noreferrer">
											<ExternalLink className="h-4 w-4" aria-hidden="true" />
											<span className="ml-1">{t("calcom.editor.status.openExternal", "Open in Cal.com")}</span>
										</a>
									:	<>
											<ExternalLink className="h-4 w-4" aria-hidden="true" />
											<span className="ml-1">{t("calcom.editor.status.openExternal", "Open in Cal.com")}</span>
										</>
									}
								</Button>
							</div>
						</CardContent>
					</Card>
				</TabsContent>

				{/* Content Tab */}
				<TabsContent value="content" className="space-y-4 mt-4">
					<Card>
						<CardHeader>
							<CardTitle className="text-base">{t("calcom.editor.section.content.title", "Widget Content")}</CardTitle>
							<CardDescription>{t("calcom.editor.section.content.description", "Customize the text shown in the booking widget")}</CardDescription>
						</CardHeader>
						<CardContent className="space-y-4">
							<div className="space-y-2">
								<Label htmlFor="title">{t("calcom.editor.title.label", "Title")}</Label>
								<Input
									id="title"
									value={getString("title")}
									onChange={(e) => handleFieldChange("title", e.target.value)}
									placeholder={t("calcom.editor.title.placeholder", "Book a Meeting")}
								/>
								<p className="text-xs text-muted-foreground">{t("calcom.editor.title.help", "Main heading shown above the calendar")}</p>
							</div>

							<div className="space-y-2">
								<Label htmlFor="description">{t("calcom.editor.description.label", "Description")}</Label>
								<Textarea
									id="description"
									value={getString("description")}
									onChange={(e) => handleFieldChange("description", e.target.value)}
									placeholder={t("calcom.editor.description.placeholder", "Choose a convenient time for your consultation...")}
									rows={3}
								/>
								<p className="text-xs text-muted-foreground">{t("calcom.editor.description.help", "Optional text shown below the title")}</p>
							</div>

							<div className="space-y-2">
								<Label htmlFor="unavailableMessage">{t("calcom.editor.unavailableMessage.label", "Booking unavailable message")}</Label>
								<Textarea
									id="unavailableMessage"
									value={getString("unavailableMessage")}
									onChange={(e) => handleFieldChange("unavailableMessage", e.target.value)}
									placeholder={t(
										"calcom.editor.unavailableMessage.placeholder",
										"Sorry — we couldn't complete your booking online. Please use our contact form and we'll get you booked in.",
									)}
									rows={3}
								/>
								<p className="text-xs text-muted-foreground">
									{t("calcom.editor.unavailableMessage.help", "Shown if an online booking can't be completed. Leave blank to use the default.")}
								</p>
							</div>
						</CardContent>
					</Card>
				</TabsContent>
			</Tabs>
		</div>
	);
}

export default CalcomBlockEditor;
