import { type ComponentProps, useState } from 'react';

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

import { useQueryClient } from '@tanstack/react-query';
import { clsx } from 'clsx';

import { useModerationCauseDescription } from '#/state/moderation/use-moderation-cause-description';
import { unstableCacheProfileView } from '#/state/queries/unstable-profile-cache';

import { BlockLink } from '#/components/BlockLink';
import * as Dialog from '#/components/Dialog';
import { ModerationDetailsDialog } from '#/components/moderation/ModerationDetailsDialog';
import { Text } from '#/components/Text';

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

import * as styles from './PostHider.css';

type Props = ComponentProps<typeof BlockLink> & {
	disabled: boolean;
	/** Diameter of the cause-icon circle (aligns with the avatar it stands in for). */
	iconSize: number;
	/** Per-surface margins on the icon circle. */
	iconClassName?: string;
	modui: DisplayRestrictions;
	profile: AnyProfileView;
	interpretFilterAsBlur?: boolean;
	/** Chrome override for the warning row (background/padding per surface). */
	hiderClassName?: string;
};

/**
 * moderation gate for a post row that renders the post or a warning row.
 *
 * @param noOverride prevents revealing the post, allowing only the details dialog.
 */
export function PostHider({
	to,
	disabled,
	modui,
	hiderClassName,
	children,
	iconSize,
	iconClassName,
	profile,
	interpretFilterAsBlur,
	...props
}: Props) {
	const queryClient = useQueryClient();
	const [override, setOverride] = useState(false);
	const handle = Dialog.useDialogHandle();
	const blur = modui.blurs[0] || (interpretFilterAsBlur ? getBlurrableFilter(modui) : undefined);
	const desc = useModerationCauseDescription(blur);

	const onBeforePress = () => {
		unstableCacheProfileView(queryClient, profile);
	};

	if (!blur || (disabled && !modui.noOverride) || override) {
		// `display: contents` host: post bodies arrive as a component (or multiple elements), so BlockLink —
		// which clones a single DOM child to inject the press handlers — needs a real element to land them on,
		// without adding a layout box.
		return (
			<BlockLink to={to} onBeforePress={onBeforePress} {...props}>
				<div style={{ display: 'contents' }}>{children}</div>
			</BlockLink>
		);
	}

	return (
		<div className={clsx(styles.row, hiderClassName)}>
			<ModerationDetailsDialog handle={handle} modcause={blur} />
			<Dialog.Trigger
				handle={handle}
				className={styles.iconButton}
				aria-label={m['components.moderation.label.learnMore.aboutWarning']()}
			>
				<span
					className={clsx(styles.iconCircle, iconClassName)}
					style={{ borderRadius: iconSize, height: iconSize, width: iconSize }}
				>
					<desc.icon className={styles.icon} />
				</span>
			</Dialog.Trigger>
			<Text className={styles.name} color="textContrastMedium" numberOfLines={1}>
				{desc.name}
			</Text>
			{!modui.noOverride && (
				<button
					type="button"
					className={styles.toggle}
					aria-label={m['components.moderation.label.showContent']()}
					onClick={() => {
						setOverride(true);
					}}
				>
					<Text color="textLink">{m['common.action.show']()}</Text>
				</button>
			)}
		</div>
	);
}

function getBlurrableFilter(modui: DisplayRestrictions): ModerationCause | undefined {
	// moderation causes get "downgraded" when they originate from embedded content; a downgraded cause
	// should *only* drive filtering in feeds, so look for a filter that isn't downgraded.
	return modui.filters.find((filter) => !filter.downgraded);
}
