/**
 * Coupon Widget
 *
 * Supports legacy copy-only coupons and richer cart-coupled coupons.
 */

import { useEffect, useMemo, useRef, useState } from 'react'
import { motion } from 'framer-motion'
import { Gift, Copy, Check, Clock, Tag, Sparkles, Truck } from 'lucide-react'
import { t } from '@/lib/i18n'
import { resolveValue } from '@/utils/resolveAppearance'
import type { GlobalValues, FieldValue } from '@/utils/resolveAppearance'
import type { CouponWidgetSettings, WooCart } from '@/types'

interface CouponData {
  code: string
  description?: string
  display_name?: string
  discount_type: 'percent' | 'fixed_cart' | 'fixed_product'
  amount: number
  expiry_date?: string | null
  minimum_amount?: number
  maximum_amount?: number | null
  applicable?: boolean
  reason?: string | null
  reason_code?: string | null
  min_spend?: number | null
  min_spend_display?: string | null
  max_spend?: number | null
  max_spend_display?: string | null
  spend_gap?: number | null
  spend_gap_display?: string | null
  eligible_products?: string[] | null
  eligible_categories?: string[] | null
  usage_remaining?: number | null
  is_applied?: boolean
  free_shipping?: boolean
  expires_soon?: boolean
}

interface CouponWidgetConfig {
  coupons: CouponData[]
  title?: string
  is_rtl?: boolean
}

interface CouponWidgetProps {
  config: CouponWidgetConfig
  widgetSettings?: CouponWidgetSettings
  globalValues?: GlobalValues
  language?: string
  isRTL?: boolean
  currencySymbol?: string
  cart?: WooCart | null
  lastBundleCouponCode?: string | null
  onCopyCode?: (code: string) => void
  onApplyCoupon?: (code: string) => Promise<{ success: boolean; message?: string; error?: string }>
  onRemoveCoupon?: (code: string) => Promise<{ success: boolean; message?: string; error?: string }>
}

function normalizeCode(code: string): string {
  return code.trim().toLowerCase()
}

export function CouponWidget({
  config,
  widgetSettings,
  globalValues = {},
  language,
  isRTL,
  currencySymbol,
  cart,
  lastBundleCouponCode,
  onCopyCode,
  onApplyCoupon,
  onRemoveCoupon,
}: CouponWidgetProps) {
  const { coupons = [], title } = config
  const [copiedCode, setCopiedCode] = useState<string | null>(null)
  const [pendingCode, setPendingCode] = useState<string | null>(null)
  const [pendingAction, setPendingAction] = useState<'apply' | 'remove' | null>(null)
  const [hoveredCopyCode, setHoveredCopyCode] = useState<string | null>(null)
  const [hoveredApplyCode, setHoveredApplyCode] = useState<string | null>(null)
  const [hoveredRemoveCode, setHoveredRemoveCode] = useState<string | null>(null)
  const [feedbackByCode, setFeedbackByCode] = useState<Record<string, { tone: 'success' | 'error'; text: string }>>({})
  const copyResetTimerRef = useRef<number | null>(null)

  const rtl = isRTL ?? config.is_rtl ?? true
  const symbol = currencySymbol
    || (window as any).boostbot_config?.woocommerce?.currency_symbol
    || '₪'
  const lang = language || 'he'

  const appliedCodes = useMemo(
    () => new Set((cart?.applied_coupons || []).map((coupon) => normalizeCode(coupon.code))),
    [cart?.applied_coupons],
  )

  useEffect(() => {
    return () => {
      if (copyResetTimerRef.current !== null) {
        window.clearTimeout(copyResetTimerRef.current)
      }
    }
  }, [])

  if (!coupons || coupons.length === 0) {
    return null
  }

  const rv = (field: FieldValue | string | undefined, fallback: string) =>
    resolveValue(field, globalValues, fallback)

  const copyToClipboard = async (code: string) => {
    try {
      await navigator.clipboard.writeText(code)
    } catch {
      const textarea = document.createElement('textarea')
      textarea.value = code
      textarea.style.position = 'fixed'
      textarea.style.opacity = '0'
      document.body.appendChild(textarea)
      textarea.select()
      document.execCommand('copy')
      document.body.removeChild(textarea)
    }

    setCopiedCode(code)

    if (copyResetTimerRef.current !== null) {
      window.clearTimeout(copyResetTimerRef.current)
    }

    copyResetTimerRef.current = window.setTimeout(() => {
      setCopiedCode((current) => (current === code ? null : current))
      copyResetTimerRef.current = null
    }, 2000)

    onCopyCode?.(code)
  }

  const setFeedback = (code: string, tone: 'success' | 'error', text: string) => {
    setFeedbackByCode((current) => ({ ...current, [code]: { tone, text } }))
  }

  const formatDiscount = (coupon: CouponData) => {
    if (coupon.discount_type === 'percent') {
      return `${coupon.amount}%`
    }
    return `${symbol}${coupon.amount}`
  }

  const formatExpiry = (dateStr: string) => {
    const locale = lang === 'he' ? 'he-IL' : 'en-US'
    return new Date(dateStr).toLocaleDateString(locale, {
      day: 'numeric',
      month: 'short',
    })
  }

  const isExpired = (dateStr?: string | null) => {
    if (!dateStr) return false
    return new Date(dateStr) < new Date()
  }

  const hasEnhancedCouponData = (coupon: CouponData) =>
    coupon.applicable !== undefined
    || coupon.is_applied !== undefined
    || coupon.reason !== undefined
    || coupon.min_spend_display !== undefined
    || coupon.spend_gap_display !== undefined

  const applyCoupon = async (coupon: CouponData) => {
    if (!onApplyCoupon) return

    setPendingCode(coupon.code)
    setPendingAction('apply')
    try {
      const result = await onApplyCoupon(coupon.code)
      if (result.success) {
        setFeedback(coupon.code, 'success', result.message || t('Coupon applied!'))
      } else {
        setFeedback(coupon.code, 'error', result.error || t('Failed to apply coupon'))
      }
    } catch (error) {
      setFeedback(coupon.code, 'error', error instanceof Error ? error.message : t('Failed to apply coupon'))
    } finally {
      setPendingCode(null)
      setPendingAction(null)
    }
  }

  const removeCoupon = async (coupon: CouponData) => {
    if (!onRemoveCoupon) return

    setPendingCode(coupon.code)
    setPendingAction('remove')
    try {
      const result = await onRemoveCoupon(coupon.code)
      if (result.success) {
        setFeedback(coupon.code, 'success', result.message || t('Coupon removed'))
      } else {
        setFeedback(coupon.code, 'error', result.error || t('Failed to remove coupon'))
      }
    } catch (error) {
      setFeedback(coupon.code, 'error', error instanceof Error ? error.message : t('Failed to remove coupon'))
    } finally {
      setPendingCode(null)
      setPendingAction(null)
    }
  }

  return (
    <motion.div
      className="p-3"
      initial={{ opacity: 0, y: 10 }}
      animate={{ opacity: 1, y: 0 }}
      dir={rtl ? 'rtl' : 'ltr'}
    >
      {title && (
        <h4 className="mb-3 flex items-center gap-2 text-sm font-medium text-gray-700">
          <Gift className="h-4 w-4 text-pink-500" />
          {title}
        </h4>
      )}

      <div className="space-y-3">
        {coupons.map((coupon, index) => {
          const normalizedCode = normalizeCode(coupon.code)
          const expired = isExpired(coupon.expiry_date)
          const enhanced = hasEnhancedCouponData(coupon)
          const isApplied = Boolean(coupon.is_applied) || appliedCodes.has(normalizedCode)
          const appliedViaBundle = Boolean(lastBundleCouponCode)
            && normalizeCode(lastBundleCouponCode ?? '') === normalizedCode
            && isApplied
          const isPending = pendingCode === coupon.code
          const canApply = enhanced && !expired && !isApplied && coupon.applicable !== false && Boolean(onApplyCoupon)
          const canRemove = enhanced && isApplied && Boolean(onRemoveCoupon)
          const feedback = feedbackByCode[coupon.code]
          const badges: string[] = []

          if (appliedViaBundle) {
            badges.push(t('Applied via bundle'))
          } else if (isApplied) {
            badges.push(t('Already applied'))
          } else if (coupon.applicable) {
            badges.push(t('Ready to apply'))
          } else if (coupon.spend_gap_display) {
            badges.push(t('Spend {amount} more').replace('{amount}', coupon.spend_gap_display))
          } else if (coupon.reason) {
            badges.push(coupon.reason)
          }

          if (coupon.expires_soon && !expired) {
            badges.push(t('Expires soon'))
          }
          if (coupon.free_shipping) {
            badges.push(t('Free shipping'))
          }

          const background = rv(widgetSettings?.container?.background, '#ffffff')
          const isLightCard = true
          const metaColor = rv(widgetSettings?.expiry?.color, isLightCard ? '#6b7280' : 'rgba(255,255,255,0.88)')
          const cardTextColor = isLightCard ? '#111827' : '#ffffff'
          const headerFontSize = rv(widgetSettings?.header?.fontSize ?? widgetSettings?.header?.font, '18px')
          const codeFontSize = rv(widgetSettings?.code?.fontSize ?? widgetSettings?.code?.font, '15px')
          const expiryFontSize = rv(widgetSettings?.expiry?.fontSize ?? widgetSettings?.expiry?.font, '11px')
          const copyButtonBackground = rv(widgetSettings?.copyButton?.background, '#3BC2D0')
          const copyButtonHoverBackground = rv(widgetSettings?.copyButton?.hoverBackground, copyButtonBackground)
          const removeLinkColor = rv(widgetSettings?.removeLink?.color, isLightCard ? '#1d4ed8' : '#ffffff')
          const removeLinkHoverColor = rv(widgetSettings?.removeLink?.hoverColor, removeLinkColor)

          return (
            <motion.div
              key={coupon.code}
              className="overflow-hidden rounded-xl"
              style={{
                background,
                borderRadius: rv(widgetSettings?.container?.borderRadius, '12px'),
                borderStyle: widgetSettings?.container?.borderStyle || 'dashed',
                borderWidth: '2px',
                borderColor: rv(widgetSettings?.container?.borderColor, isLightCard ? '#3BC2D0' : 'rgba(255,255,255,0.25)'),
                opacity: expired ? 0.62 : 1,
              }}
              initial={{ opacity: 0, x: rtl ? 20 : -20 }}
              animate={{ opacity: expired ? 0.62 : 1, x: 0 }}
              transition={{ delay: index * 0.08 }}
            >
              <div
                className="px-4 py-3"
                style={{
                  background: rv(widgetSettings?.header?.background, isLightCard ? '#3BC2D0' : 'rgba(255,255,255,0.16)'),
                  color: rv(widgetSettings?.header?.color, cardTextColor),
                }}
              >
                <div className="flex items-center gap-3">
                  <div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-white/15">
                    <Tag className="h-4 w-4" />
                  </div>
                  <div className="min-w-0 flex-1 overflow-hidden">
                    <div
                      className="font-bold leading-tight"
                      style={{ fontSize: headerFontSize }}
                    >
                      {formatDiscount(coupon)} {t('discount')}
                    </div>
                    {coupon.display_name && coupon.display_name !== coupon.code && (
                      <div className="truncate text-xs opacity-90">
                        {coupon.display_name}
                      </div>
                    )}
                  </div>
                </div>
              </div>

              <div className="space-y-3 p-4">
                <div className="flex flex-wrap gap-2">
                  {badges.map((badge) => (
                    <span
                      key={`${coupon.code}-${badge}`}
                      className="inline-flex items-center gap-1 px-2.5 py-1 text-[11px] font-semibold"
                      style={{
                        background: rv(widgetSettings?.badge?.background, isLightCard ? '#E0F2FE' : 'rgba(255,255,255,0.18)'),
                        color: rv(widgetSettings?.badge?.color, isLightCard ? '#0F172A' : '#ffffff'),
                        borderRadius: rv(widgetSettings?.badge?.borderRadius, '9999px'),
                      }}
                    >
                      {badge === t('Ready to apply') && <Sparkles className="h-3 w-3" />}
                      {badge === t('Free shipping') && <Truck className="h-3 w-3" />}
                      {badge}
                    </span>
                  ))}
                </div>

                <div
                  className="flex items-center gap-2 rounded-lg p-2"
                  style={{
                    background: rv(widgetSettings?.code?.background, isLightCard ? '#f3f4f6' : 'rgba(255,255,255,0.18)'),
                    borderRadius: rv(widgetSettings?.code?.borderRadius, '8px'),
                  }}
                >
                  <span
                    className="flex-1 font-mono font-bold tracking-[0.2em]"
                    style={{
                      color: rv(widgetSettings?.code?.color, isLightCard ? '#1f2937' : '#ffffff'),
                      fontSize: codeFontSize,
                    }}
                  >
                    {coupon.code}
                  </span>
                  <motion.button
                    type="button"
                    onClick={() => copyToClipboard(coupon.code)}
                    className="inline-flex items-center gap-1 rounded-lg px-3 py-2 text-sm font-medium transition-colors"
                    style={{
                      background: copiedCode === coupon.code
                        ? '#10B981'
                        : hoveredCopyCode === coupon.code
                          ? copyButtonHoverBackground
                          : copyButtonBackground,
                      color: rv(widgetSettings?.copyButton?.color, '#ffffff'),
                      borderRadius: rv(widgetSettings?.copyButton?.borderRadius, '8px'),
                    }}
                    whileTap={{ scale: 0.97 }}
                    onMouseEnter={() => setHoveredCopyCode(coupon.code)}
                    onMouseLeave={() => setHoveredCopyCode((current) => (current === coupon.code ? null : current))}
                    disabled={expired}
                  >
                    {copiedCode === coupon.code ? (
                      <>
                        <Check className="h-3.5 w-3.5" />
                        <span aria-live="polite">{t('Copied!')}</span>
                      </>
                    ) : (
                      <>
                        <Copy className="h-3.5 w-3.5" />
                        {t('Copy code')}
                      </>
                    )}
                  </motion.button>
                </div>

                <div className="flex flex-wrap items-center gap-4 text-xs" style={{ color: metaColor, fontSize: expiryFontSize }}>
                  {coupon.expiry_date && (
                    <span className="flex items-center gap-1">
                      <Clock className="h-3 w-3" />
                      {expired ? t('Expired') : `${t('Until')} ${formatExpiry(coupon.expiry_date)}`}
                    </span>
                  )}
                  {(coupon.min_spend_display || (coupon.minimum_amount != null && coupon.minimum_amount > 0)) && (
                    <span>
                      {t('Over')} {coupon.min_spend_display || `${symbol}${coupon.minimum_amount}`}
                    </span>
                  )}
                  {coupon.max_spend_display && (
                    <span>{t('Up to')} {coupon.max_spend_display}</span>
                  )}
                  {coupon.usage_remaining != null && (
                    <span>{t('{count} uses left').replace('{count}', String(coupon.usage_remaining))}</span>
                  )}
                </div>

                {enhanced && (
                  <>
                    {(coupon.eligible_products?.length || coupon.eligible_categories?.length) && (
                      <div className="space-y-1 text-xs" style={{ color: metaColor }}>
                        {coupon.eligible_products?.length ? (
                          <div>{t('Eligible products')}: {coupon.eligible_products.join(', ')}</div>
                        ) : null}
                        {coupon.eligible_categories?.length ? (
                          <div>{t('Eligible categories')}: {coupon.eligible_categories.join(', ')}</div>
                        ) : null}
                      </div>
                    )}

                    <div className="flex flex-wrap items-center gap-3">
                      {canApply && (
                        <motion.button
                          type="button"
                          onClick={() => void applyCoupon(coupon)}
                          className="rounded-lg px-3 py-2 text-sm font-semibold"
                          style={{
                            background: hoveredApplyCode === coupon.code
                              ? copyButtonHoverBackground
                              : copyButtonBackground,
                            color: rv(widgetSettings?.copyButton?.color, '#ffffff'),
                            borderRadius: rv(widgetSettings?.copyButton?.borderRadius, '8px'),
                          }}
                          whileTap={{ scale: 0.97 }}
                          onMouseEnter={() => setHoveredApplyCode(coupon.code)}
                          onMouseLeave={() => setHoveredApplyCode((current) => (current === coupon.code ? null : current))}
                          disabled={isPending}
                        >
                          {isPending && pendingAction === 'apply' ? t('Applying...') : t('Apply to Cart')}
                        </motion.button>
                      )}

                      {canRemove && (
                        <button
                          type="button"
                          className="text-sm font-medium underline underline-offset-4"
                          style={{
                            color: hoveredRemoveCode === coupon.code ? removeLinkHoverColor : removeLinkColor,
                          }}
                          onClick={() => void removeCoupon(coupon)}
                          onMouseEnter={() => setHoveredRemoveCode(coupon.code)}
                          onMouseLeave={() => setHoveredRemoveCode((current) => (current === coupon.code ? null : current))}
                          disabled={isPending}
                        >
                          {isPending && pendingAction === 'remove' ? t('Removing...') : t('Remove')}
                        </button>
                      )}
                    </div>
                  </>
                )}

                {feedback && (
                  <div
                    className="text-sm font-medium"
                    style={{ color: feedback.tone === 'success' ? '#16A34A' : '#DC2626' }}
                  >
                    {feedback.text}
                  </div>
                )}
              </div>
            </motion.div>
          )
        })}
      </div>
    </motion.div>
  )
}

export default CouponWidget
