'use no memo'; // composition props usually invalidate the generated wrapper caches

import { type ComponentType, type ReactNode, type SVGProps, useId } from 'react';

import { AlertDialog } from '@base-ui/react/alert-dialog';

import { useConstant } from '#/lib/hooks/use-constant';

import { useRegisterDialog } from '#/components/Dialog/registry';
import * as styles from '#/components/Prompt/Prompt.css';
import { Text } from '#/components/Text';
import { Button, ButtonIcon, ButtonText } from '#/components/web/Button';

import { m } from '#/paraglide/messages';

type Color = 'negative' | 'negative_subtle' | 'primary' | 'secondary';

export const Trigger = AlertDialog.Trigger;

/** Creates a detached handle to open/close a Prompt imperatively or from a detached Trigger. */
export const createHandle = AlertDialog.createHandle;

/** A detached handle for opening/closing a Prompt */
export type PromptHandle<T = void> = AlertDialog.Handle<T>;

/** Component-local prompt handle. */
export function usePromptHandle<T = void>(): PromptHandle<T> {
	const handle = useConstant(createHandle<T>);
	return handle;
}

type Size = 'default' | 'wide';

/** A confirmation dialog (no backdrop/Escape dismissal — an explicit action is required). */
export function Outer({
	children,
	handle,
	size = 'default',
}: {
	children: ReactNode;
	handle: PromptHandle;
	size?: Size;
}) {
	const id = useId();
	const registerOpen = useRegisterDialog(id, () => handle.close());
	return (
		<AlertDialog.Root handle={handle} onOpenChange={(open) => registerOpen(open)}>
			<AlertDialog.Portal className={styles.portal}>
				<AlertDialog.Backdrop className={styles.backdrop} forceRender />
				<AlertDialog.Viewport className={styles.viewport}>
					<AlertDialog.Popup className={styles.popup({ size })}>{children}</AlertDialog.Popup>
				</AlertDialog.Viewport>
			</AlertDialog.Portal>
		</AlertDialog.Root>
	);
}

/** Groups the title + description above the actions. */
export function Content({ children }: { children: ReactNode }) {
	return <div className={styles.content}>{children}</div>;
}

export function TitleText({ children }: { children: ReactNode }) {
	return (
		<AlertDialog.Title className={styles.title} render={<Text size="xl" weight="semiBold" />}>
			{children}
		</AlertDialog.Title>
	);
}

export function DescriptionText({ children }: { children: ReactNode }) {
	return (
		<AlertDialog.Description className={styles.description} render={<Text color="textContrastHigh" />}>
			{children}
		</AlertDialog.Description>
	);
}

/** A vertical list of icon + text rows explaining what an action does (the "here's what happens" body). */
export function Rows({ children }: { children: ReactNode }) {
	return <div className={styles.rows}>{children}</div>;
}

/** A single explainer row: a muted leading icon beside its description. */
export function Row({
	children,
	icon: Icon,
}: {
	children: ReactNode;
	icon: ComponentType<SVGProps<SVGSVGElement>>;
}) {
	return (
		<div className={styles.row}>
			<Icon className={styles.rowIcon} />
			<Text className={styles.rowText} color="textContrastHigh">
				{children}
			</Text>
		</div>
	);
}

export function Actions({ children }: { children: ReactNode }) {
	return <div className={styles.actions}>{children}</div>;
}

export function Action({
	onPress,
	color = 'primary',
	cta,
	disabled = false,
	icon,
	shouldCloseOnPress = true,
}: {
	onPress: () => void;
	color?: Color;
	cta?: string;
	disabled?: boolean;
	icon?: ComponentType<SVGProps<SVGSVGElement>>;
	shouldCloseOnPress?: boolean;
}) {
	const label = cta ?? m['common.action.confirm']();
	const content = (
		<>
			<ButtonText>{label}</ButtonText>
			{icon && <ButtonIcon icon={icon} />}
		</>
	);

	if (!shouldCloseOnPress) {
		return (
			<Button color={color} disabled={disabled} label={label} onClick={onPress} size="large" variant="solid">
				{content}
			</Button>
		);
	}

	return (
		<AlertDialog.Close
			disabled={disabled}
			onClick={onPress}
			render={
				<Button color={color} label={label} size="large" variant="solid">
					{content}
				</Button>
			}
		/>
	);
}

export function Cancel({ cta }: { cta?: string }) {
	const label = cta ?? m['common.action.cancel']();

	return (
		<AlertDialog.Close
			render={
				<Button color="secondary" label={label} size="large" variant="solid">
					<ButtonText>{label}</ButtonText>
				</Button>
			}
		/>
	);
}

export function Basic({
	handle,
	title,
	description,
	cancelButtonCta,
	confirmButtonCta,
	onConfirm,
	confirmButtonColor,
	showCancel = true,
}: {
	handle: PromptHandle;
	title: string;
	description?: string;
	cancelButtonCta?: string;
	confirmButtonCta?: string;
	onConfirm: () => void;
	confirmButtonColor?: Color;
	showCancel?: boolean;
}) {
	return (
		<Outer handle={handle}>
			<Content>
				<TitleText>{title}</TitleText>
				{description && <DescriptionText>{description}</DescriptionText>}
			</Content>
			<Actions>
				<Action onPress={onConfirm} color={confirmButtonColor} cta={confirmButtonCta} />
				{showCancel && <Cancel cta={cancelButtonCta} />}
			</Actions>
		</Outer>
	);
}
