import { useEffect, useState } from 'react'
import { createPortal } from 'react-dom'
import { X } from 'lucide-react'
import { ApiError } from '../lib/api'
import {
  countSelectedOptions,
  getProductVariationValues,
  saveProductVariationValues,
  type ProductVariationSelection,
} from '../services/productVariationService'
import { MultiSelectDropdown } from './MultiSelectDropdown'
import styles from './VariationsModal.module.css'

interface ProductVariantsModalProps {
  open: boolean
  productId: string
  categoryId: string
  productName: string
  onClose: () => void
  onVariantsChange?: (count: number) => void
}

const ANIMATION_MS = 220

export function ProductVariantsModal({
  open,
  productId,
  categoryId,
  productName,
  onClose,
  onVariantsChange,
}: ProductVariantsModalProps) {
  const [mounted, setMounted] = useState(open)
  const [closing, setClosing] = useState(false)
  const [variations, setVariations] = useState<ProductVariationSelection[]>([])
  const [isLoading, setIsLoading] = useState(false)
  const [isSaving, setIsSaving] = useState(false)
  const [error, setError] = useState('')

  useEffect(() => {
    if (open) {
      setMounted(true)
      setClosing(false)
    } else if (mounted) {
      setClosing(true)
      const timer = setTimeout(() => {
        setMounted(false)
        setClosing(false)
      }, ANIMATION_MS)
      return () => clearTimeout(timer)
    }
  }, [open, mounted])

  useEffect(() => {
    if (!open || !productId) return

    const controller = new AbortController()
    void loadData(controller.signal)
    return () => controller.abort()
  }, [open, productId, categoryId])

  async function loadData(signal?: AbortSignal) {
    setIsLoading(true)
    setError('')

    try {
      const data = await getProductVariationValues(productId, signal)
      setVariations(data.variations)
      onVariantsChange?.(countSelectedOptions(data.variations))
    } catch (err) {
      if (err instanceof DOMException && err.name === 'AbortError') return
      if (err instanceof ApiError) {
        setError(err.message)
      } else {
        setError('Unable to load product variations.')
      }
    } finally {
      setIsLoading(false)
    }
  }

  useEffect(() => {
    if (!mounted || closing) return
    const onKey = (e: KeyboardEvent) => {
      if (e.key === 'Escape') onClose()
    }
    document.addEventListener('keydown', onKey)
    return () => document.removeEventListener('keydown', onKey)
  }, [mounted, closing, onClose])

  if (!mounted) return null

  function handleSelectionChange(variationId: string, optionIds: string[]) {
    setVariations((prev) =>
      prev.map((variation) =>
        variation.id === variationId
          ? { ...variation, selectedOptionIds: optionIds }
          : variation,
      ),
    )
  }

  async function handleSave() {
    setIsSaving(true)
    setError('')

    try {
      const data = await saveProductVariationValues(productId, variations)
      setVariations(data.variations)
      onVariantsChange?.(countSelectedOptions(data.variations))
      onClose()
    } catch (err) {
      if (err instanceof ApiError) {
        setError(err.message)
      } else {
        setError('Unable to save product variations.')
      }
    } finally {
      setIsSaving(false)
    }
  }

  return createPortal(
    <div
      className={`${styles.overlay} ${closing ? styles.overlayOut : styles.overlayIn}`}
      onClick={onClose}
    >
      <div
        className={`${styles.modal} ${closing ? styles.modalOut : styles.modalIn}`}
        onClick={(e) => e.stopPropagation()}
        role="dialog"
        aria-modal="true"
        aria-labelledby="product-variants-title"
      >
        <div className={styles.header}>
          <div>
            <h3 id="product-variants-title" className={styles.title}>
              Product Variations
            </h3>
            {productName && <p className={styles.subtitle}>{productName}</p>}
          </div>
          <button className={styles.closeBtn} onClick={onClose} aria-label="Close">
            <X size={20} />
          </button>
        </div>

        <div className={styles.body}>
          {!categoryId && (
            <p className={styles.errorText}>
              Assign a category to this product before managing variations.
            </p>
          )}

          {error && <p className={styles.errorText}>{error}</p>}

          {isLoading ? (
            <p className={styles.emptyText}>Loading variations...</p>
          ) : variations.length === 0 ? (
            <p className={styles.emptyText}>
              {categoryId
                ? 'This category has no variations. Add variations on the category first.'
                : 'No variations available.'}
            </p>
          ) : (
            <div className={styles.variationFields}>
              {variations.map((variation) => (
                <div key={variation.id} className={styles.field}>
                  <label htmlFor={`variation-${variation.id}`}>{variation.name}</label>
                  <MultiSelectDropdown
                    id={`variation-${variation.id}`}
                    options={variation.options.map((option) => ({
                      value: option.id,
                      label: option.label,
                    }))}
                    value={variation.selectedOptionIds}
                    onChange={(optionIds) => handleSelectionChange(variation.id, optionIds)}
                    placeholder={`Select ${variation.name.toLowerCase()} values`}
                    disabled={isSaving}
                  />
                </div>
              ))}
            </div>
          )}

          <div className={styles.actions}>
            <button
              type="button"
              className={styles.cancelBtn}
              onClick={onClose}
              disabled={isSaving}
            >
              Cancel
            </button>
            <button
              type="button"
              className={styles.submitBtn}
              onClick={() => void handleSave()}
              disabled={!categoryId || isLoading || isSaving || variations.length === 0}
            >
              {isSaving ? 'Saving…' : 'Save variations'}
            </button>
          </div>
        </div>
      </div>
    </div>
  ,
  document.body,
  )
}
