import { createContext, useContext } from 'react'

import type { ReactNode } from 'react'

type DialogueVariant = 'default' | 'danger'

type ConfirmOptions = { title:        string
			description?: ReactNode
			confirmText?: string
			cancelText?:  string
			variant?:     DialogueVariant }

type AlertOptions = { title:        string
		      description?: ReactNode
		      okText?:      string }

type Choice<T extends string> = { value:    T
				  label:    string
				  variant?: DialogueVariant }

type ChoiceOptions<T extends string> = { title:         string
					 description?:  ReactNode
					 choices:       Choice<T>[]
					 cancelText?:   string }

type DialogueFormAction = {
  label:      string
  placement?: 'start' | 'end'
  variant?:   DialogueVariant
  disabled?:  boolean
  onSelect:   () => Promise<boolean | void> | boolean | void }

type DialogueFormControls = {
  close:      () => void
  setActions: (actions: DialogueFormAction[]) => void
  confirm:    (options: ConfirmOptions) => Promise<boolean> }

type DialogueFormOptions = { title:         string
			     description?:  ReactNode
			     body:          (controls: DialogueFormControls) => ReactNode
			     cancelText?:   string
			     size?:         'default' | 'large' }

type DialogueAPI =
    { confirm:  (options: ConfirmOptions) => Promise<boolean>
      alert:    (options: AlertOptions) => Promise<void>
      choice:   <T extends string> (options: ChoiceOptions<T>) => Promise<T | null>
      form:     (options: DialogueFormOptions) => Promise<void> }

const DialogueContext = createContext<DialogueAPI | null> (null)

const useDialogue = () => {
  const dialogue = useContext (DialogueContext)

  if (dialogue == null)
    throw new Error ('useDialogue must be used inside DialogueProvider')

  return dialogue
}

export { DialogueContext, useDialogue }
export default useDialogue
export type {
    AlertOptions,
    Choice,
    ChoiceOptions,
    ConfirmOptions,
    DialogueAPI,
    DialogueFormAction,
    DialogueFormControls,
    DialogueFormOptions,
    DialogueVariant }
