import { useEffect, useMemo, useState } from 'react'
import { createPortal } from 'react-dom'
import { Plus, X } from 'lucide-react'
import { useLocale } from '@meshkee/dashboard-ui'
import { useT } from '../i18n/useT'
import { ApiError } from '../lib/api'
import {
  getProductVariationValues,
  type ProductVariationSelection,
} from '../services/productVariationService'
import {
  syncProductStoreItems,
  type StoreItem,
} from '../services/storeItemService'
import { createId } from '../utils/id'
import { formatIrtInput, parseIrtInput } from '../utils/irtPrice'
import {
  createEmptyStoreItemRow,
  getVariationOptions,
  type StoreItemDraftRow,
} from '../utils/storeItemRows'
import { Tooltip } from './Tooltip'
import modalStyles from './VariationsModal.module.css'
import rowStyles from './CreateStoreItemsModal.module.css'

interface EditStoreItemsModalProps {
  open: boolean
  productTitle: string
  productNameFa: string
  items: StoreItem[]
  onClose: () => void
  onSaved?: (items: StoreItem[]) => void
}

const ANIMATION_MS = 220

function itemsToRows(storeItems: StoreItem[]): StoreItemDraftRow[] {
  if (storeItems.length === 0) return [createEmptyStoreItemRow()]

  return storeItems.map((item) => {
    const selections: Record<string, string> = {}
    for (const selection of item.selections) {
      selections[selection.variationId] = selection.optionId
    }

    return {
      id: createId(),
      storeItemId: item.id,
      selections,
      price: item.price !== null ? formatIrtInput(String(item.price)) : '',
      stock: item.stockQuantity !== null ? String(item.stockQuantity) : '1',
    }
  })
}

export function EditStoreItemsModal({
  open,
  productTitle,
  productNameFa,
  items,
  onClose,
  onSaved,
}: EditStoreItemsModalProps) {
  const t = useT()
  const { locale } = useLocale()
  const isFa = locale === 'fa'
  const [mounted, setMounted] = useState(open)
  const [closing, setClosing] = useState(false)
  const [variations, setVariations] = useState<ProductVariationSelection[]>([])
  const [rows, setRows] = useState<StoreItemDraftRow[]>([])
  const [removedIds, setRemovedIds] = useState<string[]>([])
  const [isLoading, setIsLoading] = useState(false)
  const [isSubmitting, setIsSubmitting] = useState(false)
  const [error, setError] = useState('')

  const productId = items[0]?.productId ?? ''

  const formVariations = useMemo(
    () => variations.filter((variation) => getVariationOptions(variation).length > 0),
    [variations],
  )

  const gridTemplate = useMemo(() => {
    const variationCols = formVariations.map(() => 'minmax(110px, 1fr)').join(' ')
    const cols = [variationCols, 'minmax(120px, 1fr)', '90px', '32px'].filter((part) => part).join(' ')
    return cols || 'minmax(120px, 1fr) 90px 32px'
  }, [formVariations])

  useEffect(() => {
    if (open && productId) {
      setMounted(true)
      setClosing(false)
      setRemovedIds([])
      setRows(itemsToRows(items))
      setError('')
      const controller = new AbortController()
      void loadVariations(productId, controller.signal)
      return () => controller.abort()
    }

    if (mounted && !open) {
      setClosing(true)
      const timer = setTimeout(() => {
        setMounted(false)
        setClosing(false)
      }, ANIMATION_MS)
      return () => clearTimeout(timer)
    }
  }, [open, productId, items, mounted])

  async function loadVariations(nextProductId: string, signal?: AbortSignal) {
    setIsLoading(true)
    try {
      const data = await getProductVariationValues(nextProductId, signal)
      setVariations(data.variations)
    } catch (err) {
      if (err instanceof DOMException && err.name === 'AbortError') return
      if (err instanceof ApiError) {
        setError(err.message)
      } else {
        setError(t('storeItems.create.errorVariations'))
      }
    } 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 || !productId) return null

  function updateRow(rowId: string, patch: Partial<StoreItemDraftRow>) {
    setRows((prev) => prev.map((row) => (row.id === rowId ? { ...row, ...patch } : row)))
  }

  function updateRowSelection(rowId: string, variationId: string, optionId: string) {
    setRows((prev) =>
      prev.map((row) => {
        if (row.id !== rowId) return row
        const nextSelections = { ...row.selections }
        if (!optionId) {
          delete nextSelections[variationId]
        } else {
          nextSelections[variationId] = optionId
        }
        return { ...row, selections: nextSelections }
      }),
    )
  }

  function addRow() {
    setRows((prev) => [...prev, { ...createEmptyStoreItemRow(), id: createId() }])
  }

  function removeRow(rowId: string) {
    setRows((prev) => {
      if (prev.length <= 1) return prev
      const target = prev.find((row) => row.id === rowId)
      if (target?.storeItemId) {
        setRemovedIds((ids) => [...ids, target.storeItemId!])
      }
      return prev.filter((row) => row.id !== rowId)
    })
  }

  const canSubmit =
    rows.length > 0 &&
    rows.every((row) => {
      const price = parseIrtInput(row.price)
      const stock = Number(row.stock)
      return price !== null && price >= 0 && row.stock.trim() !== '' && !Number.isNaN(stock) && stock >= 0
    }) &&
    !isSubmitting &&
    !isLoading

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    if (!canSubmit) return

    setIsSubmitting(true)
    setError('')

    try {
      const data = await syncProductStoreItems({
        productId,
        items: rows.map((row) => ({
          id: row.storeItemId,
          selections: formVariations.flatMap((variation) => {
            const optionId = row.selections[variation.id]
            if (!optionId) return []
            return [{ variationId: variation.id, optionId }]
          }),
          price: parseIrtInput(row.price)!,
          stockQuantity: Number(row.stock),
        })),
        removedIds,
      })
      onSaved?.(data.items)
      onClose()
    } catch (err) {
      if (err instanceof ApiError) {
        setError(err.message)
      } else {
        setError(t('storeItems.edit.errorSave'))
      }
    } finally {
      setIsSubmitting(false)
    }
  }

  const subtitle = isFa
    ? [productNameFa, productTitle].filter(Boolean).join(' / ')
    : [productTitle, productNameFa].filter(Boolean).join(' / ')

  return createPortal(
    <div
      className={`${modalStyles.overlay} ${closing ? modalStyles.overlayOut : modalStyles.overlayIn}`}
      onClick={onClose}
    >
      <div
        className={`${modalStyles.modal} ${rowStyles.modalWide} ${closing ? modalStyles.modalOut : modalStyles.modalIn}`}
        onClick={(e) => e.stopPropagation()}
        role="dialog"
        aria-modal="true"
        aria-labelledby="edit-store-items-title"
        lang={isFa ? 'fa' : 'en'}
        dir={isFa ? 'rtl' : 'ltr'}
      >
        <div className={modalStyles.header}>
          <div>
            <h3 id="edit-store-items-title" className={modalStyles.title}>
              {t('storeItems.edit.title')}
            </h3>
            <p className={modalStyles.subtitle}>{subtitle}</p>
          </div>
          <button
            className={modalStyles.closeBtn}
            onClick={onClose}
            aria-label={t('common.close')}
          >
            <X size={20} />
          </button>
        </div>

        <form className={modalStyles.body} onSubmit={(e) => void handleSubmit(e)}>
          {isLoading ? (
            <p className={modalStyles.emptyText}>{t('storeItems.create.loadingVariations')}</p>
          ) : (
            <>
              <div
                className={rowStyles.itemRowHeader}
                style={{ gridTemplateColumns: gridTemplate }}
              >
                {formVariations.map((variation) => (
                  <span key={variation.id}>{variation.name}</span>
                ))}
                <span>{t('storeItems.create.price')}</span>
                <span>{t('storeItems.create.stock')}</span>
                <span />
              </div>

              <div className={rowStyles.itemRows}>
                {rows.map((row) => (
                  <div
                    key={row.id}
                    className={rowStyles.itemRow}
                    style={{ gridTemplateColumns: gridTemplate }}
                  >
                    {formVariations.map((variation) => {
                      const options = getVariationOptions(variation)
                      return (
                        <select
                          key={variation.id}
                          className={rowStyles.compactInput}
                          value={row.selections[variation.id] ?? ''}
                          onChange={(e) =>
                            updateRowSelection(row.id, variation.id, e.target.value)
                          }
                          disabled={isSubmitting}
                        >
                          <option value="">—</option>
                          {options.map((option) => (
                            <option key={option.id} value={option.id}>
                              {option.label}
                            </option>
                          ))}
                        </select>
                      )
                    })}
                    <input
                      type="text"
                      inputMode="numeric"
                      className={rowStyles.compactInput}
                      value={row.price}
                      onChange={(e) => updateRow(row.id, { price: formatIrtInput(e.target.value) })}
                      placeholder="0"
                      disabled={isSubmitting}
                    />
                    <input
                      type="number"
                      min="0"
                      step="1"
                      className={rowStyles.compactInput}
                      value={row.stock}
                      onChange={(e) => updateRow(row.id, { stock: e.target.value })}
                      disabled={isSubmitting}
                    />
                    <div className={rowStyles.removeCell}>
                      <Tooltip label={t('storeItems.create.removeRow')}>
                        <button
                          type="button"
                          className={modalStyles.removeRowBtn}
                          onClick={() => removeRow(row.id)}
                          disabled={rows.length <= 1 || isSubmitting}
                          aria-label={t('storeItems.create.removeRow')}
                        >
                          <X size={16} />
                        </button>
                      </Tooltip>
                    </div>
                  </div>
                ))}
              </div>

              <button
                type="button"
                className={rowStyles.addRowBtn}
                onClick={addRow}
                disabled={isSubmitting}
              >
                <Plus size={16} />
                {t('storeItems.create.addRow')}
              </button>
            </>
          )}

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

          <div className={modalStyles.actions}>
            <button
              type="button"
              className={modalStyles.cancelBtn}
              onClick={onClose}
              disabled={isSubmitting}
            >
              {t('storeItems.create.cancel')}
            </button>
            <button type="submit" className={modalStyles.submitBtn} disabled={!canSubmit}>
              {isSubmitting ? t('storeItems.edit.saving') : t('storeItems.edit.save')}
            </button>
          </div>
        </form>
      </div>
    </div>
  ,
  document.body,
  )
}
