import type { ReactNode, Ref } from 'react';

import type { AnyProfileView } from '@atcute/bluesky';
import { DisplayContext, getDisplayRestrictions, type ModerationDecision } from '@atcute/bluesky-moderation';

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

import { profileTarget } from '#/lib/routes/targets';

import { useProfileShadow } from '#/state/cache/profile-shadow';
import { unstableCacheProfileView } from '#/state/queries/profile';

import { niceDate } from '#/locale/intl/datetime';

import { useActorStatus } from '#/features/liveNow/use-actor-status';

import { PreviewableUserAvatar } from '#/components/PreviewableUserAvatar';
import { ProfileBadges } from '#/components/ProfileBadges';
import { ProfileHoverCard } from '#/components/ProfileHoverCard';
import { Text, type TextProps } from '#/components/Text';
import { Tooltip } from '#/components/Tooltip';
import { InlineLinkText } from '#/components/web/Link';

import { m } from '#/paraglide/messages';
import type { RouteTarget } from '#/router';

import * as css from './PostMeta.css';
import { TimeElapsed } from './TimeElapsed';

type AuthorLinkProps = Pick<
	TextProps,
	'align' | 'className' | 'color' | 'leading' | 'numberOfLines' | 'size' | 'weight'
> & {
	children: ReactNode;
	/** When set, render as inert text instead of a navigable link. */
	disabled: boolean;
	label: string;
	onPress: () => void;
	/** Forwarded to the host node (`<a>`, or `<span>` when inert) so it can back a headless trigger. */
	ref?: Ref<HTMLElement>;
	to: RouteTarget;
};

/** A link in the meta row that collapses to plain {@link Text} when the surrounding row is non-interactive. */
function AuthorLink({ disabled, label, onPress, ref, to, ...text }: AuthorLinkProps) {
	'use no memo'; // forwarded text props invalidate the generated wrapper cache

	// the ref lands on a different element per branch (`<span>` vs `<a>`); Base UI hands us a generic
	// element ref either way, so narrow it at the boundary.
	if (disabled) {
		return <Text ref={ref} {...text} />;
	}
	return (
		<InlineLinkText
			label={label}
			onPress={onPress}
			// oxlint-disable-next-line typescript/no-unsafe-type-assertion -- `RefObject` is invariant; this branch always renders an `<a>`
			ref={ref as Ref<HTMLAnchorElement>}
			to={to}
			{...text}
		/>
	);
}

interface PostMetaOpts {
	author: AnyProfileView;
	className?: string;
	moderation: ModerationDecision | undefined;
	postTarget: RouteTarget;
	timestamp: string;
	linkDisabled?: boolean;
	showAvatar?: boolean;
	avatarSize?: number;
	onOpenAuthor?: () => void;
}

function PostMeta(opts: PostMetaOpts): ReactNode {
	const author = useProfileShadow(opts.author);
	const handle = author.handle;
	const authorTarget = profileTarget(author.did);
	const queryClient = useQueryClient();
	const onOpenAuthor = opts.onOpenAuthor;
	const onBeforePressAuthor = () => {
		unstableCacheProfileView(queryClient, author);
		onOpenAuthor?.();
	};
	const onBeforePressPost = () => {
		unstableCacheProfileView(queryClient, author);
	};

	const timestampLabel = niceDate(opts.timestamp);
	const { isActive: live } = useActorStatus(author);

	const disabled = opts.linkDisabled ?? false;

	return (
		<div className={clsx(css.row, opts.className)}>
			{opts.showAvatar && (
				<div className={css.avatar}>
					<PreviewableUserAvatar
						size={opts.avatarSize || 16}
						profile={author}
						moderation={
							opts.moderation && getDisplayRestrictions(opts.moderation, DisplayContext.ProfileMedia)
						}
						type={author.associated?.labeler ? 'labeler' : 'user'}
						live={live}
						hideLiveBadge
						disableNavigation={disabled}
						tabIndex={-1}
					/>
				</div>
			)}
			<div className={css.author}>
				<ProfileHoverCard actor={author.did}>
					<AuthorLink
						className={css.handle}
						color="textContrastHigh"
						weight="semiBold"
						disabled={disabled}
						label={m['common.profile.action.view']()}
						numberOfLines={1}
						onPress={onBeforePressAuthor}
						size="md"
						to={authorTarget}
					>
						{handle}
					</AuthorLink>
				</ProfileHoverCard>

				<ProfileBadges className={css.badges} profile={author} size="sm" />

				<TimeElapsed timestamp={opts.timestamp}>
					{({ timeElapsed }) => (
						<>
							{/* eslint-disable-next-line bsky-internal/avoid-unwrapped-text */}
							<span aria-hidden> </span>

							<Tooltip label={timestampLabel}>
								<AuthorLink
									align="right"
									className={css.timestamp}
									color="textContrastMedium"
									disabled={disabled}
									label={timestampLabel}
									onPress={onBeforePressPost}
									size="md"
									to={opts.postTarget}
								>
									{timeElapsed}
								</AuthorLink>
							</Tooltip>
						</>
					)}
				</TimeElapsed>
			</div>
		</div>
	);
}
export { PostMeta };
