import { createElement, type ReactNode, useCallback, useRef, useState } from 'react'
import { ConfirmDialog } from 'src/components/menu/overlays/ConfirmDialog'

type ConfirmOptions = {
  title: string
  message?: string
  confirmLabel: string
  cancelLabel?: string
  destructive?: boolean
}

type State = Required<Pick<ConfirmOptions, 'title' | 'confirmLabel'>> &
  Pick<ConfirmOptions, 'message' | 'cancelLabel' | 'destructive'>

// useConfirmDialog — imperative wrapper over ConfirmDialog. Call `confirm(opts)`
// anywhere to get a Promise<boolean>; render `dialog` once at the leaf of your
// tree. Consolidates the 20+ Alert.alert confirmation sites that each used to
// duplicate state + JSX for the same flow.
//
// Why: a controlled ConfirmDialog is correct for the menu-intent render layer
// (where the trigger and the dialog are colocated), but awkward for ad-hoc
// confirms. The promise form matches how Alert.alert feels at the call site.

export function useConfirmDialog() {
  const [state, setState] = useState<State | null>(null)
  const resolverRef = useRef<((v: boolean) => void) | null>(null)

  const resolve = useCallback((value: boolean) => {
    resolverRef.current?.(value)
    resolverRef.current = null
    setState(null)
  }, [])

  const confirm = useCallback((opts: ConfirmOptions): Promise<boolean> => {
    // If one dialog is already open, resolve it false before opening a new one —
    // prevents orphaned promises when a user triggers back-to-back confirms.
    resolverRef.current?.(false)
    return new Promise<boolean>((res) => {
      resolverRef.current = res
      setState({
        title: opts.title,
        message: opts.message,
        confirmLabel: opts.confirmLabel,
        cancelLabel: opts.cancelLabel,
        destructive: opts.destructive,
      })
    })
  }, [])

  const dialog: ReactNode = state
    ? createElement(ConfirmDialog, {
        open: true,
        onOpenChange: (open: boolean) => {
          // Defer the cancel-resolution by one microtask: when the user taps
          // the action button, Tamagui's `asChild` composition fires the
          // wrapping DialogClose's `onOpenChange(false)` BEFORE the inner
          // Button's `onPress`. Without the defer, every action tap resolves
          // with false (treated as a dismiss) and the inner `onConfirm`'s
          // `resolve(true)` arrives a tick too late to a null resolverRef.
          // Microtask ordering: onOpenChange schedules resolve(false), then
          // onPress runs synchronously and calls resolve(true) — which wins
          // because the queued microtask sees a null resolverRef.
          if (!open) queueMicrotask(() => resolve(false))
        },
        title: state.title,
        message: state.message ?? '',
        confirmLabel: state.confirmLabel,
        cancelLabel: state.cancelLabel,
        destructive: state.destructive,
        onConfirm: () => resolve(true),
      })
    : null

  return { confirm, dialog }
}
