import { computed, ref, watch, type Ref } from 'vue'

export type AdminToastTone = 'success' | 'error' | 'info'

export interface AdminToastOptions {
  durationMs?: number
  persistent?: boolean
  key?: string
}

export interface AdminToast {
  id: number
  message: string
  tone: AdminToastTone
  persistent?: boolean
  key?: string
}

const activeToast = ref<AdminToast | null>(null)
let toastId = 0
let hideTimer: number | undefined

export function useAdminToast() {
  function dismissAdminToast(target?: number | string) {
    if (typeof target === 'number' && activeToast.value?.id !== target) return
    if (typeof target === 'string' && activeToast.value?.key !== target) return
    activeToast.value = null

    if (hideTimer !== undefined && typeof window !== 'undefined') {
      window.clearTimeout(hideTimer)
      hideTimer = undefined
    }
  }

  function showAdminToast(
    message: string,
    tone: AdminToastTone = 'info',
    options: number | AdminToastOptions = tone === 'error' ? 6200 : 4200,
  ) {
    const trimmedMessage = message.trim()
    if (!trimmedMessage) return
    const resolvedOptions = typeof options === 'number' ? { durationMs: options } : options
    const durationMs = resolvedOptions.durationMs ?? (tone === 'error' ? 6200 : 4200)
    const persistent = resolvedOptions.persistent ?? false
    const key = resolvedOptions.key?.trim() || undefined

    if (activeToast.value?.persistent && activeToast.value.key !== key) {
      return activeToast.value.id
    }

    if (
      key
      && activeToast.value?.key === key
      && activeToast.value.message === trimmedMessage
      && activeToast.value.tone === tone
      && activeToast.value.persistent === persistent
    ) {
      return activeToast.value.id
    }

    if (hideTimer !== undefined && typeof window !== 'undefined') {
      window.clearTimeout(hideTimer)
      hideTimer = undefined
    }

    const id = ++toastId
    activeToast.value = { id, message: trimmedMessage, tone, persistent, key }

    if (!persistent && typeof window !== 'undefined') {
      hideTimer = window.setTimeout(() => dismissAdminToast(id), durationMs)
    }

    return id
  }

  return {
    toast: computed(() => activeToast.value),
    showAdminToast,
    dismissAdminToast,
  }
}

export function watchAdminToast(adminMessage: Ref<string>, adminError: Ref<string>) {
  const { showAdminToast } = useAdminToast()

  watch(
    adminMessage,
    (message) => {
      if (message.trim()) {
        showAdminToast(message, 'success')
      }
    },
    { flush: 'post' },
  )

  watch(
    adminError,
    (error) => {
      if (error.trim()) {
        showAdminToast(error, 'error')
      }
    },
    { flush: 'post' },
  )
}

export function watchAdminErrorToast(adminError: Ref<string>) {
  const { showAdminToast } = useAdminToast()

  watch(
    adminError,
    (error) => {
      if (error.trim()) {
        showAdminToast(error, 'error')
      }
    },
    { flush: 'post' },
  )
}
