/**
 * Bundle Builder Widget
 *
 * The AI gathers bundle criteria through natural conversation first, then this
 * widget renders the resulting bundle directly from the prefilled criteria.
 *
 * @package BoostBot
 * @since 1.0.0
 * @updated 1.9.0
 */

import { useState, useCallback, useEffect, useRef, type ReactNode } from 'react'
import { motion, AnimatePresence } from 'framer-motion'
import {
  AlertCircle,
  Check,
  Package,
  RefreshCw,
  Search,
  ShoppingCart,
  Sparkles,
} from 'lucide-react'
import {
  BundleDisplay,
  type BundleActionState,
  type BundleBuilderWidgetSettings,
  type BundleData,
  type BundleProduct,
} from './BundleDisplay'
import { t } from '@/lib/i18n'
import { useChatStore } from '@/store/chatStore'
import { getCartTelemetryFields, trackCommerceEvent } from '@/services/commerceTelemetry'
import { resolveValue, type GlobalValues } from '@/utils/resolveAppearance'

type BundleScreenState = 'loading' | 'display' | 'error' | 'empty' | 'success'

interface SimpleProduct {
  id: number
  name: string
  price: number
  image?: string
  quantity?: number
}

interface BundleBuilderCriteria {
  budget?: number
  category?: string
  preferences?: string[]
}

interface BundleBuilderConfig {
  bundle?: BundleData
  products?: SimpleProduct[]
  discount_percent?: number
  show_savings?: boolean
  allow_customization?: boolean
  success_message?: string
  empty_message?: string
  error_message?: string
  budget?: number
  category?: string
  preferences?: string | string[]
}

interface BundleBuilderWidgetProps {
  config: BundleBuilderConfig
  widgetId?: number
  widgetSettings?: BundleBuilderWidgetSettings
  globalValues?: GlobalValues
  onAddToCart?: (bundleId: number, bundle: BundleData, couponCode?: string) => Promise<{ success: boolean; message: string }>
  onBuildBundle?: (criteria: BundleBuilderCriteria) => Promise<BundleData>
  onSwapItem?: (payload: {
    bundleId: number
    swapOutId: number
    bundle: BundleData
    criteria: BundleBuilderCriteria
  }) => Promise<BundleData>
  onClose?: () => void
  isRtl?: boolean
  primaryColor?: string
  language?: string
}

function normalizePreferences(value: string | string[] | undefined): string[] | undefined {
  if (!value) {
    return undefined
  }

  if (Array.isArray(value)) {
    const normalized = value.map(item => String(item).trim()).filter(Boolean)
    return normalized.length > 0 ? normalized : undefined
  }

  const normalized = value
    .split(/[,،]/)
    .map(item => item.trim())
    .filter(Boolean)

  return normalized.length > 0 ? normalized : undefined
}

function createBundleFromProducts(config: BundleBuilderConfig): BundleData | null {
  if (!config.products || config.products.length === 0) {
    return null
  }

  const originalPrice = config.products.reduce((sum, product) => {
    const quantity = product.quantity || 1
    return sum + (product.price * quantity)
  }, 0)
  const discountPercent = config.discount_percent || 10
  const totalPrice = originalPrice * (1 - (discountPercent / 100))
  const products: BundleProduct[] = config.products.map(product => ({
    id: product.id,
    name: product.name,
    price: Number((product.price * (1 - (discountPercent / 100))).toFixed(2)),
    original_price: product.price,
    regular_price: product.price,
    image: product.image || '',
    permalink: '#',
    rating: 0,
    on_sale: false,
    savings: Number((product.price * (discountPercent / 100)).toFixed(2)),
  }))

  return {
    bundle_id: Date.now(),
    products,
    total_price: Number(totalPrice.toFixed(2)),
    original_price: Number(originalPrice.toFixed(2)),
    savings: Number((originalPrice - totalPrice).toFixed(2)),
    savings_percent: discountPercent,
  }
}

function recalculateBundle(bundle: BundleData, products: BundleProduct[]): BundleData {
  const originalPrice = products.reduce((sum, product) => sum + (product.original_price || product.price || 0), 0)
  const totalPrice = products.reduce((sum, product) => sum + (product.price || 0), 0)
  const savings = originalPrice - totalPrice
  const savingsPercent = originalPrice > 0 ? (savings / originalPrice) * 100 : 0

  return {
    ...bundle,
    products,
    total_price: Number(totalPrice.toFixed(2)),
    original_price: Number(originalPrice.toFixed(2)),
    savings: Number(savings.toFixed(2)),
    savings_percent: Number(savingsPercent.toFixed(1)),
    coupon: undefined,
  }
}

export function BundleBuilderWidget({
  config,
  widgetId,
  widgetSettings,
  globalValues,
  onAddToCart,
  onBuildBundle,
  onSwapItem,
  onClose,
  isRtl = true,
  primaryColor = '#3BC2D0',
  language,
}: BundleBuilderWidgetProps) {
  const { conversationId, visitorId, currentBotId, config: chatConfig, cart } = useChatStore()
  const initialCriteria: BundleBuilderCriteria = {
    budget: config.budget,
    category: config.category,
    preferences: normalizePreferences(config.preferences),
  }

  const [screenState, setScreenState] = useState<BundleScreenState>('loading')
  const [actionState, setActionState] = useState<BundleActionState>('idle')
  const [bundle, setBundle] = useState<BundleData | null>(config.bundle || null)
  const [criteria, setCriteria] = useState<BundleBuilderCriteria>(initialCriteria)
  const [error, setError] = useState<string | null>(null)
  const [successMessage, setSuccessMessage] = useState<string | null>(null)
  const [activeProductId, setActiveProductId] = useState<number | null>(null)
  const bundleRef = useRef<BundleData | null>(config.bundle || null)
  const criteriaRef = useRef<BundleBuilderCriteria>(initialCriteria)
  const trackedBundleSignaturesRef = useRef<Set<string>>(new Set())

  const rv = (field: Parameters<typeof resolveValue>[0], fallback: string) => resolveValue(field, globalValues, fallback)
  const canCustomize = config.allow_customization !== false

  useEffect(() => {
    bundleRef.current = bundle
  }, [bundle])

  useEffect(() => {
    criteriaRef.current = criteria
  }, [criteria])

  useEffect(() => {
    if (!bundle || !bundle.products?.length) {
      return
    }

    const signature = [
      bundle.bundle_id,
      bundle.products.map(product => product.id).join(','),
      bundle.total_price,
    ].join(':')

    if (trackedBundleSignaturesRef.current.has(signature)) {
      return
    }

    trackedBundleSignaturesRef.current.add(signature)

    trackCommerceEvent({
      event_type: 'bundle_built',
      conversation_id: conversationId,
      visitor_id: visitorId,
      bot_id: currentBotId,
      language: chatConfig.language,
      widget_type: 'bundle_builder',
      widget_id: widgetId ?? null,
      bundle_id: bundle.bundle_id,
      bundle_size: bundle.products.length,
      bundle_value: Number(bundle.total_price ?? 0),
      currency_code: cart?.currency_code,
      ...getCartTelemetryFields(cart),
      metadata: {
        category: criteria.category || null,
        budget: criteria.budget ?? null,
        preferences: criteria.preferences || [],
      },
    })
  }, [bundle, cart, chatConfig.language, conversationId, criteria.budget, criteria.category, criteria.preferences, currentBotId, visitorId, widgetId])

  const buildBundle = useCallback(async (
    overrideCriteria?: {
      budget?: number
      category?: string
      preferences?: string | string[]
    },
    options?: { preserveDisplay?: boolean },
  ) => {
    if (!onBuildBundle) {
      return
    }

    const currentCriteria = criteriaRef.current
    const nextCriteria: BundleBuilderCriteria = {
      budget: overrideCriteria?.budget ?? currentCriteria.budget,
      category: overrideCriteria?.category ?? currentCriteria.category,
      preferences: normalizePreferences(overrideCriteria?.preferences) ?? currentCriteria.preferences,
    }
    const existingBundle = bundleRef.current
    const hasLoadedBundle = Boolean(existingBundle?.products?.length)
    const preserveLoadedBundle = Boolean(options?.preserveDisplay || hasLoadedBundle)

    setCriteria(nextCriteria)
    setError(null)
    setSuccessMessage(null)

    if (preserveLoadedBundle) {
      setActionState('rebuilding')
      setScreenState('display')
    } else {
      setActionState('idle')
      setScreenState('loading')
    }

    try {
      const result = await onBuildBundle(nextCriteria)

      if (result && result.products && result.products.length > 0) {
        setBundle(result)
        setScreenState('display')
      } else {
        setBundle(null)
        setScreenState('empty')
      }
    } catch (err) {
      console.debug('[BoostBot] Bundle build error:', err)
      const message = err instanceof Error ? err.message : (config.error_message || t('Error building bundle'))
      if (preserveLoadedBundle) {
        setError(message)
        setScreenState('display')
      } else {
        setError(message)
        setScreenState('error')
      }
    } finally {
      setActionState('idle')
      setActiveProductId(null)
    }
  }, [config.error_message, onBuildBundle])

  useEffect(() => {
    const nextCriteria: BundleBuilderCriteria = {
      budget: config.budget,
      category: config.category,
      preferences: normalizePreferences(config.preferences),
    }
    const inlineBundle = config.bundle || createBundleFromProducts(config)
    criteriaRef.current = nextCriteria
    setCriteria(nextCriteria)
    setError(null)
    setSuccessMessage(null)
    setActionState('idle')
    setActiveProductId(null)

    if (inlineBundle) {
      bundleRef.current = inlineBundle
      setBundle(inlineBundle)
      setScreenState('display')
      return
    }

    if (onBuildBundle) {
      bundleRef.current = null
      void buildBundle(nextCriteria, { preserveDisplay: false })
      return
    }

    bundleRef.current = null
    setBundle(null)
    setScreenState('empty')
  }, [
    buildBundle,
    config.bundle,
    config.products,
    config.discount_percent,
    config.budget,
    config.category,
    config.preferences,
    onBuildBundle,
  ])

  const handleAddToCart = useCallback(async () => {
    if (!bundle || !onAddToCart) {
      return
    }

    setActionState('adding')
    setError(null)

    try {
      const couponCode = bundle.coupon?.code
      const result = await onAddToCart(bundle.bundle_id, bundle, couponCode)

      if (result.success) {
        setSuccessMessage(config.success_message || result.message || t('Bundle added to cart!'))
        setScreenState('success')
      } else {
        setError(result.message)
        setScreenState('display')
      }
    } catch (err) {
      console.debug('[BoostBot] Bundle add to cart error:', err)
      setError(err instanceof Error ? err.message : t('Error adding to cart'))
      setScreenState('display')
    } finally {
      setActionState('idle')
    }
  }, [bundle, config.success_message, onAddToCart])

  const handleRemoveProduct = useCallback((productId: number) => {
    if (!bundle) {
      return
    }

    const nextProducts = bundle.products.filter(product => product.id !== productId)
    setError(null)

    if (nextProducts.length === 0) {
      setBundle(null)
      setScreenState('empty')
      return
    }

    setBundle(recalculateBundle(bundle, nextProducts))
    setScreenState('display')
  }, [bundle])

  const handleSwapProduct = useCallback(async (productId: number) => {
    if (!bundle || !onSwapItem) {
      return
    }

    setActionState('swapping')
    setActiveProductId(productId)
    setError(null)

    try {
      const result = await onSwapItem({
        bundleId: bundle.bundle_id,
        swapOutId: productId,
        bundle,
        criteria,
      })

      setBundle(previous => ({
        ...(previous || bundle),
        ...result,
        message: result.message || previous?.message || bundle.message,
      }))
      setScreenState(result.products?.length ? 'display' : 'empty')
    } catch (err) {
      console.debug('[BoostBot] Swap bundle item error:', err)
      setError(err instanceof Error ? err.message : t('Could not swap bundle item'))
      setScreenState('display')
    } finally {
      setActionState('idle')
      setActiveProductId(null)
    }
  }, [bundle, criteria, onSwapItem])

  const handleRetry = useCallback(() => {
    if (bundleRef.current?.products?.length) {
      setError(null)
      setScreenState('display')
      return
    }

    if (onBuildBundle) {
      void buildBundle(undefined, { preserveDisplay: false })
      return
    }

    onClose?.()
  }, [buildBundle, onBuildBundle, onClose])

  const cartUrl = (() => {
    const bundleCartUrl = bundle?.add_to_cart_url
    if (bundleCartUrl) {
      try {
        const url = new URL(bundleCartUrl, window.location.origin)
        url.search = ''
        return url.toString()
      } catch {
        return bundleCartUrl
      }
    }
    return (window as any).boostbot_config?.woocommerce?.cart_url || '/cart'
  })()

  const renderStateCard = (options: {
    key: string
    icon: ReactNode
    title: string
    description: string
    background: string
    iconBackground: string
    iconColor: string
    action?: ReactNode
  }) => (
    <motion.div
      key={options.key}
      initial={{ opacity: 0, scale: 0.96 }}
      animate={{ opacity: 1, scale: 1 }}
      exit={{ opacity: 0 }}
      style={{
        background: options.background,
        borderRadius: rv(widgetSettings?.container?.borderRadius, '16px'),
        boxShadow: rv(widgetSettings?.container?.shadow, '0 10px 24px rgba(15, 23, 42, 0.12)'),
        border: `1px solid ${rv(widgetSettings?.container?.borderColor, '#E5E7EB')}`,
        padding: '24px',
        maxWidth: '360px',
        marginInline: 'auto',
        textAlign: 'center',
      }}
    >
      <div
        className="mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full"
        style={{ background: options.iconBackground, color: options.iconColor }}
      >
        {options.icon}
      </div>
      <h3
        style={{
          color: rv(widgetSettings?.states?.titleColor, '#0F172A'),
          fontSize: rv(widgetSettings?.header?.titleFontSize, '18px'),
          fontWeight: rv(widgetSettings?.header?.titleFontWeight, '700'),
          margin: 0,
        }}
      >
        {options.title}
      </h3>
      <p
        style={{
          color: rv(widgetSettings?.states?.descriptionColor, '#64748B'),
          fontSize: rv(widgetSettings?.header?.subtitleFontSize, '13px'),
          margin: '10px 0 0',
        }}
      >
        {options.description}
      </p>
      {options.action && <div className="mt-5 flex justify-center">{options.action}</div>}
    </motion.div>
  )

  return (
    <div className="bundle-widget" dir={isRtl ? 'rtl' : 'ltr'}>
      <AnimatePresence mode="wait">
        {screenState === 'loading' && !bundle && renderStateCard({
          key: 'loading',
          icon: (
            <motion.div animate={{ rotate: 360 }} transition={{ duration: 1.2, repeat: Infinity, ease: 'linear' }}>
              <Package className="h-7 w-7" />
            </motion.div>
          ),
          title: t('Preparing your bundle...'),
          description: t('Just a moment'),
          background: rv(widgetSettings?.states?.loadingBackground, '#FFFFFF'),
          iconBackground: `${primaryColor}14`,
          iconColor: rv(widgetSettings?.states?.loadingIconColor, primaryColor),
        })}

        {screenState === 'display' && bundle && (
          <motion.div
            key="display"
            initial={{ opacity: 0, y: 20 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -20 }}
          >
            <BundleDisplay
              bundle={bundle}
              widgetSettings={widgetSettings}
              globalValues={globalValues}
              onAddToCart={handleAddToCart}
              onRebuild={canCustomize && onBuildBundle ? () => { void buildBundle(undefined, { preserveDisplay: true }) } : undefined}
              onSwapProduct={canCustomize && onSwapItem ? (productId) => { void handleSwapProduct(productId) } : undefined}
              onRemoveProduct={canCustomize ? handleRemoveProduct : undefined}
              isRtl={isRtl}
              primaryColor={primaryColor}
              actionState={actionState}
              activeProductId={activeProductId}
              feedbackMessage={error}
              currencySymbol={(window as any).boostbot_config?.woocommerce?.currency_symbol || '₪'}
              language={language}
            />
          </motion.div>
        )}

        {screenState === 'empty' && renderStateCard({
          key: 'empty',
          icon: <Search className="h-7 w-7" />,
          title: t('Request another bundle'),
          description: config.empty_message || t('No matching products found. Try broadening your criteria.'),
          background: rv(widgetSettings?.states?.emptyBackground, '#FFFFFF'),
          iconBackground: `${primaryColor}12`,
          iconColor: rv(widgetSettings?.states?.emptyIconColor, primaryColor),
          action: onBuildBundle ? (
            <motion.button
              type="button"
              onClick={handleRetry}
              className="flex items-center gap-2"
              style={{
                background: rv(widgetSettings?.primaryButton?.background, primaryColor),
                color: rv(widgetSettings?.primaryButton?.color, '#FFFFFF'),
                borderRadius: rv(widgetSettings?.primaryButton?.borderRadius, '12px'),
                border: `1px solid ${rv(widgetSettings?.primaryButton?.borderColor, primaryColor)}`,
                padding: '10px 16px',
                fontWeight: 700,
                fontSize: rv(widgetSettings?.primaryButton?.fontSize, '14px'),
              }}
              whileHover={{ scale: 1.03 }}
              whileTap={{ scale: 0.97 }}
            >
              <RefreshCw className="h-4 w-4" />
              <span>{t('Try again')}</span>
            </motion.button>
          ) : undefined,
        })}

        {screenState === 'error' && renderStateCard({
          key: 'error',
          icon: <AlertCircle className="h-7 w-7" />,
          title: t('Error'),
          description: error || config.error_message || t('Something went wrong. Please try again.'),
          background: rv(widgetSettings?.states?.errorBackground, '#FFFFFF'),
          iconBackground: '#FEE2E2',
          iconColor: rv(widgetSettings?.states?.errorIconColor, '#DC2626'),
          action: (
            <motion.button
              type="button"
              onClick={handleRetry}
              className="flex items-center gap-2"
              style={{
                background: rv(widgetSettings?.primaryButton?.background, primaryColor),
                color: rv(widgetSettings?.primaryButton?.color, '#FFFFFF'),
                borderRadius: rv(widgetSettings?.primaryButton?.borderRadius, '12px'),
                border: `1px solid ${rv(widgetSettings?.primaryButton?.borderColor, primaryColor)}`,
                padding: '10px 16px',
                fontWeight: 700,
                fontSize: rv(widgetSettings?.primaryButton?.fontSize, '14px'),
              }}
              whileHover={{ scale: 1.03 }}
              whileTap={{ scale: 0.97 }}
            >
              <RefreshCw className="h-4 w-4" />
              <span>{t('Try again')}</span>
            </motion.button>
          ),
        })}

        {screenState === 'success' && renderStateCard({
          key: 'success',
          icon: <Check className="h-7 w-7" />,
          title: t('Excellent!'),
          description: successMessage || t('Bundle added to cart!'),
          background: rv(widgetSettings?.states?.successBackground, '#FFFFFF'),
          iconBackground: `${primaryColor}14`,
          iconColor: rv(widgetSettings?.states?.successIconColor, primaryColor),
          action: (
            <div className="flex flex-wrap justify-center gap-3">
              <motion.a
                href={cartUrl}
                className="flex items-center gap-2"
                style={{
                  background: rv(widgetSettings?.primaryButton?.background, primaryColor),
                  color: rv(widgetSettings?.primaryButton?.color, '#FFFFFF'),
                  borderRadius: rv(widgetSettings?.primaryButton?.borderRadius, '12px'),
                  border: `1px solid ${rv(widgetSettings?.primaryButton?.borderColor, primaryColor)}`,
                  padding: '10px 16px',
                  fontWeight: 700,
                  fontSize: rv(widgetSettings?.primaryButton?.fontSize, '14px'),
                  textDecoration: 'none',
                }}
                whileHover={{ scale: 1.03 }}
                whileTap={{ scale: 0.97 }}
              >
                <ShoppingCart className="h-4 w-4" />
                <span>{t('Go to cart')}</span>
              </motion.a>
              <motion.button
                type="button"
                onClick={onClose}
                className="flex items-center gap-2"
                style={{
                  background: rv(widgetSettings?.secondaryButton?.background, '#FFFFFF'),
                  color: rv(widgetSettings?.secondaryButton?.color, '#334155'),
                  borderRadius: rv(widgetSettings?.secondaryButton?.borderRadius, '12px'),
                  border: `1px solid ${rv(widgetSettings?.secondaryButton?.borderColor, '#CBD5E1')}`,
                  padding: '10px 16px',
                  fontWeight: 600,
                  fontSize: rv(widgetSettings?.secondaryButton?.fontSize, '14px'),
                }}
                whileHover={{ scale: 1.03 }}
                whileTap={{ scale: 0.97 }}
              >
                <Sparkles className="h-4 w-4" />
                <span>{t('Continue browsing')}</span>
              </motion.button>
            </div>
          ),
        })}
      </AnimatePresence>
    </div>
  )
}

export default BundleBuilderWidget
