import type { AppBskyActorDefs, AppBskyFeedDefs, AppBskyUnspeccedGetPostThreadV2 } from '@atcute/bluesky';
import type { ModerationDecision } from '@atcute/bluesky-moderation';
import type { ResourceUri } from '@atcute/lexicons';

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

import type { ResolvedLink } from '#/lib/api/resolve';
import { useNonReactiveCallback } from '#/lib/hooks/use-non-reactive-callback';
import type { VideoAsset } from '#/lib/media/video/types';
import { recordUriToShareUrl } from '#/lib/routes/app-links';

import { RQKEY_LINK } from '#/state/queries/resolve-link-key';

import { composerDialogHandle } from '#/components/dialogs/handles';
import * as Toast from '#/components/Toast';

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

export interface ComposerOptsPostRef {
	uri: ResourceUri;
	cid: string;
	text: string;
	langs?: string[];
	author: AppBskyActorDefs.ProfileViewBasic;
	embed?: AppBskyFeedDefs.PostView['embed'];
	moderation?: ModerationDecision;
}

export type OnPostSuccessData =
	| {
			replyToUri?: string;
			posts: AppBskyUnspeccedGetPostThreadV2.ThreadItem[];
	  }
	| undefined;

export interface ComposerOpts {
	replyTo?: ComposerOptsPostRef;
	onPost?: (postUri: string | undefined) => void;
	onPostSuccess?: (data: OnPostSuccessData) => void;
	quote?: AppBskyFeedDefs.PostView;
	mention?: string; // handle of user to mention
	text?: string;
	videoUri?: VideoAsset;
}

/**
 * registry id for the singleton composer dialog. this stable constant allows the discard flow to close all
 * other dialogs without threading an id through context.
 */
export const COMPOSER_DIALOG_ID = 'composer';

/**
 * thin imperative API over the global composer dialog (see `composerDialogHandle` in
 * `#/components/dialogs/handles`). a hook rather than a plain function because precaching the quoted post
 * needs the active account's query client.
 */
export function useOpenComposer() {
	const queryClient = useQueryClient();

	const openComposer = useNonReactiveCallback((opts: ComposerOpts) => {
		if (opts.quote) {
			const appUrl = recordUriToShareUrl(opts.quote.uri);
			if (appUrl) {
				const resolved: ResolvedLink = {
					type: 'record',
					kind: 'post',
					record: {
						cid: opts.quote.cid,
						uri: opts.quote.uri,
					},
					view: opts.quote,
				};

				queryClient.setQueryData(RQKEY_LINK(appUrl), resolved);
			}
		}
		const author = opts.replyTo?.author || opts.quote?.author;
		const isBlocked = !!(
			author &&
			(author.viewer?.blocking || author.viewer?.blockedBy || author.viewer?.blockingByList)
		);
		if (isBlocked) {
			Toast.show(m['common.block.interactionError'](), {
				type: 'warning',
			});
			return;
		}
		// Never replace an already open composer.
		if (composerDialogHandle.isOpen) {
			return;
		}
		composerDialogHandle.openWithPayload(opts);
	});

	return { openComposer };
}

/** closes the global composer without raising its discard prompt. */
export function closeComposer(): void {
	if (composerDialogHandle.isOpen) {
		composerDialogHandle.close();
	}
}
