import React, { useEffect, useRef } from 'react'

const providerAdapters = {
  turnstile: {
    globalName: 'turnstile',
    render(api, container, { siteKey, theme, onToken }) {
      return api.render(container, {
        sitekey: siteKey,
        theme,
        callback: (token) => onToken?.(token || ''),
        'expired-callback': () => onToken?.(''),
        'error-callback': () => onToken?.(''),
      })
    },
    cleanup(api, widgetId, container, onToken) {
      if (widgetId !== null && api?.remove) {
        api.remove(widgetId)
      }
      if (container) {
        container.innerHTML = ''
      }
      onToken?.('')
    },
  },
  recaptcha: {
    globalName: 'grecaptcha',
    render(api, container, { siteKey, theme, onToken }) {
      return api.render(container, {
        sitekey: siteKey,
        theme,
        callback: (token) => onToken?.(token || ''),
        'expired-callback': () => onToken?.(''),
        'error-callback': () => onToken?.(''),
      })
    },
    cleanup(api, widgetId, container, onToken) {
      if (widgetId !== null && api?.reset) {
        api.reset(widgetId)
      }
      if (container) {
        container.innerHTML = ''
      }
      onToken?.('')
    },
  },
  hcaptcha: {
    globalName: 'hcaptcha',
    render(api, container, { siteKey, theme, onToken }) {
      return api.render(container, {
        sitekey: siteKey,
        theme,
        callback: (token) => onToken?.(token || ''),
        'expired-callback': () => onToken?.(''),
        'error-callback': () => onToken?.(''),
      })
    },
    cleanup(api, widgetId, container, onToken) {
      if (widgetId !== null && api?.remove) {
        api.remove(widgetId)
      }
      if (container) {
        container.innerHTML = ''
      }
      onToken?.('')
    },
  },
}

function loadCaptchaScript(src) {
  if (!src) {
    return Promise.resolve()
  }

  if (!window.__skinbaseCaptchaScripts) {
    window.__skinbaseCaptchaScripts = {}
  }

  if (!window.__skinbaseCaptchaScripts[src]) {
    window.__skinbaseCaptchaScripts[src] = new Promise((resolve, reject) => {
      const existing = document.querySelector(`script[src="${src}"]`)

      if (existing) {
        if (existing.dataset.loaded === 'true') {
          resolve()
          return
        }

        existing.addEventListener('load', () => resolve(), { once: true })
        existing.addEventListener('error', () => reject(new Error(`Failed to load captcha script: ${src}`)), { once: true })
        return
      }

      const script = document.createElement('script')
      script.src = src
      script.async = true
      script.defer = true
      script.addEventListener('load', () => {
        script.dataset.loaded = 'true'
        resolve()
      }, { once: true })
      script.addEventListener('error', () => reject(new Error(`Failed to load captcha script: ${src}`)), { once: true })
      document.head.appendChild(script)
    })
  }

  return window.__skinbaseCaptchaScripts[src]
}

export default function TurnstileField({ provider = 'turnstile', siteKey, scriptUrl = '', onToken, theme = 'dark', className = '' }) {
  const containerRef = useRef(null)
  const widgetIdRef = useRef(null)

  useEffect(() => {
    const adapter = providerAdapters[provider] || providerAdapters.turnstile

    if (!siteKey || !containerRef.current) {
      return undefined
    }

    let cancelled = false
    let intervalId = null

    const mountWidget = () => {
      const api = window[adapter.globalName]

      if (cancelled || !api?.render || widgetIdRef.current !== null) {
        return
      }

      widgetIdRef.current = adapter.render(api, containerRef.current, {
        siteKey,
        theme,
        onToken,
      })
    }

    loadCaptchaScript(scriptUrl).catch(() => onToken?.('')).finally(() => {
      const api = window[adapter.globalName]
      if (typeof api?.ready === 'function') {
        api.ready(mountWidget)
      } else {
        mountWidget()
      }

      if (widgetIdRef.current === null) {
        intervalId = window.setInterval(mountWidget, 250)
      }
    })

    return () => {
      cancelled = true
      if (intervalId) {
        window.clearInterval(intervalId)
      }
      adapter.cleanup(window[adapter.globalName], widgetIdRef.current, containerRef.current, onToken)
      widgetIdRef.current = null
    }
  }, [className, onToken, provider, scriptUrl, siteKey, theme])

  if (!siteKey) {
    return null
  }

  return <div ref={containerRef} className={className} />
}
