import type { ReactNode } from 'react';

import type { ModerationCause } from '@atcute/bluesky-moderation';

import { clsx } from 'clsx';

import type { AppModerationCause } from '#/lib/moderation/causes';
import { BSKY_LABELER_DID } from '#/lib/moderation/labelers';

import { useModerationCauseDescription } from '#/state/moderation/use-moderation-cause-description';

import * as Dialog from '#/components/Dialog';
import { ModerationDetailsDialog } from '#/components/moderation/ModerationDetailsDialog';
import { Text } from '#/components/Text';
import { UserAvatar } from '#/components/UserAvatar';
import * as styles from '#/components/web/Pills.css';

import RepostOffIcon from '#/icons/central/ArrowsRepeatRightLeftOff_round_outlined_radius1_stroke2.svg';
import { m } from '#/paraglide/messages';

export type { AppModerationCause };

export type CommonProps = {
	size?: 'lg' | 'sm';
};

/** A wrapping flex row of moderation pills. The `className` escape hatch lets a caller add outer spacing. */
export function Row({
	children,
	className,
	size = 'sm',
}: { children: ReactNode; className?: string } & CommonProps) {
	return <div className={clsx(styles.row({ size }), className)}>{children}</div>;
}

export type LabelProps = {
	cause: AppModerationCause | ModerationCause;
	/**
	 * When true, render a static pill that doesn't open the moderation-details dialog (e.g. inside a hover
	 * card).
	 */
	disableDetailsDialog?: boolean;
	noBg?: boolean;
} & CommonProps;

/** A single moderation pill: a glyph/avatar + label that opens the moderation-details dialog when pressed. */
export function Label({ cause, disableDetailsDialog, noBg, size = 'sm' }: LabelProps) {
	const handle = Dialog.useDialogHandle();
	const desc = useModerationCauseDescription(cause);
	const isLabeler = !!(desc.sourceType && desc.sourceDid);
	const isBlueskyLabel = desc.sourceType === 'labeler' && desc.sourceDid === BSKY_LABELER_DID;
	// the glyph tracks the pill's text size rather than an icon token, and must match the avatar it swaps with.
	const glyphSize = size === 'lg' ? 16 : 12;

	const inner = (
		<>
			{isBlueskyLabel || !isLabeler ? (
				<desc.icon height={glyphSize} width={glyphSize} />
			) : (
				<UserAvatar avatar={desc.sourceAvi} size={glyphSize} type="user" />
			)}
			<Text
				className={styles.pillText}
				color="textContrastMedium"
				numberOfLines={1}
				size={size === 'lg' ? 'sm' : 'xs'}
				weight="semiBold"
			>
				{desc.name}
			</Text>
		</>
	);

	if (disableDetailsDialog) {
		return <div className={styles.pill({ bg: !noBg, size })}>{inner}</div>;
	}

	return (
		<>
			<Dialog.Trigger aria-label={desc.name} className={styles.pill({ bg: !noBg, size })} handle={handle}>
				{inner}
			</Dialog.Trigger>
			<ModerationDetailsDialog handle={handle} modcause={cause} />
		</>
	);
}

/** A static pill marking a profile whose reposts the signed-in user has muted. */
export function MutedOnlyReposts({ size = 'sm' }: CommonProps) {
	// the glyph tracks the pill's text size rather than an icon token, matching {@link Label}.
	const glyphSize = size === 'lg' ? 16 : 12;

	return (
		<div className={styles.pill({ size })}>
			<RepostOffIcon height={glyphSize} width={glyphSize} />
			<Text
				className={styles.pillText}
				color="textContrastMedium"
				numberOfLines={1}
				size={size === 'lg' ? 'sm' : 'xs'}
				weight="semiBold"
			>
				{m['common.mute.repostsHidden']()}
			</Text>
		</div>
	);
}

/** A static pill marking a profile the signed-in user is followed by. */
export function FollowsYou() {
	return (
		<div className={styles.followsYou}>
			<Text size="xs">{m['common.follow.followsYou']()}</Text>
		</div>
	);
}
