import { useEffect, useRef, useState } from 'react'
import { createPortal } from 'react-dom'
import { Plus, Sparkles, Trash2, X } from 'lucide-react'
import type { TechnicalFieldType, TechnicalFormFieldDraft } from '../types/technicalForm'
import { createId } from '../utils/id'
import styles from './VariationsModal.module.css'
import fieldStyles from './TechnicalFormModal.module.css'
import aiStyles from '../styles/ai.module.css'

interface TechnicalFormModalProps {
  open: boolean
  categoryName: string
  fields: TechnicalFormFieldDraft[]
  isLoading?: boolean
  isSaving?: boolean
  isGenerating?: boolean
  error?: string
  onClose: () => void
  onChange: (fields: TechnicalFormFieldDraft[]) => void
  onSave: () => void
  onGenerate?: () => void
  onGenerateClick?: () => void
}

const ANIMATION_MS = 220

const FIELD_TYPE_LABELS: Record<TechnicalFieldType, string> = {
  text: 'Text',
  textarea: 'Textarea',
  select: 'Select',
  multi_select: 'Multi',
}

function createEmptyField(): TechnicalFormFieldDraft {
  return {
    id: createId(),
    label: '',
    type: 'text',
    isRequired: false,
    options: [''],
  }
}

export function TechnicalFormModal({
  open,
  categoryName,
  fields,
  isLoading = false,
  isSaving = false,
  isGenerating = false,
  error = '',
  onClose,
  onChange,
  onSave,
  onGenerate,
  onGenerateClick,
}: TechnicalFormModalProps) {
  const [mounted, setMounted] = useState(open)
  const [closing, setClosing] = useState(false)
  const optionInputRefs = useRef<Record<string, (HTMLInputElement | null)[]>>({})
  const pendingFocus = useRef<{ fieldId: string; index: number } | null>(null)

  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 (!pendingFocus.current) return
    const { fieldId, index } = pendingFocus.current
    optionInputRefs.current[fieldId]?.[index]?.focus()
    pendingFocus.current = null
  }, [fields])

  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 updateField(fieldId: string, patch: Partial<TechnicalFormFieldDraft>) {
    onChange(
      fields.map((field) => (field.id === fieldId ? { ...field, ...patch } : field)),
    )
  }

  function removeField(fieldId: string) {
    onChange(fields.filter((field) => field.id !== fieldId))
  }

  function addField() {
    onChange([...fields, createEmptyField()])
  }

  function updateOption(fieldId: string, index: number, value: string) {
    onChange(
      fields.map((field) => {
        if (field.id !== fieldId) return field
        return {
          ...field,
          options: field.options.map((option, optionIndex) =>
            optionIndex === index ? value : option,
          ),
        }
      }),
    )
  }

  function addOption(fieldId: string) {
    onChange(
      fields.map((field) =>
        field.id === fieldId ? { ...field, options: [...field.options, ''] } : field,
      ),
    )
  }

  function removeOption(fieldId: string, index: number) {
    onChange(
      fields.map((field) => {
        if (field.id !== fieldId) return field
        const next = field.options.filter((_, optionIndex) => optionIndex !== index)
        return { ...field, options: next.length ? next : [''] }
      }),
    )
  }

  function handleOptionKeyDown(
    fieldId: string,
    index: number,
    e: React.KeyboardEvent<HTMLInputElement>,
    options: string[],
  ) {
    if (e.key !== 'Enter') return
    e.preventDefault()

    const nextIndex = index + 1
    if (nextIndex < options.length) {
      optionInputRefs.current[fieldId]?.[nextIndex]?.focus()
      return
    }

    pendingFocus.current = { fieldId, index: nextIndex }
    addOption(fieldId)
  }

  const canSave =
    !isLoading &&
    !isSaving &&
    !isGenerating &&
    fields.every((field) => {
      if (!field.label.trim()) return false
      if (field.type === 'select' || field.type === 'multi_select') {
        return field.options.some((option) => option.trim())
      }
      return true
    })

  return createPortal(
    <div
      className={`${styles.overlay} ${closing ? styles.overlayOut : styles.overlayIn}`}
      onClick={onClose}
    >
      <div
        className={`${styles.modal} ${fieldStyles.modalWide} ${closing ? styles.modalOut : styles.modalIn}`}
        onClick={(e) => e.stopPropagation()}
        role="dialog"
        aria-modal="true"
        aria-labelledby="technical-form-title"
      >
        <div className={styles.header}>
          <div>
            <h3 id="technical-form-title" className={styles.title}>
              Technical Data Form
            </h3>
            {categoryName && <p className={styles.subtitle}>{categoryName}</p>}
          </div>
          <button className={styles.closeBtn} onClick={onClose} aria-label="Close">
            <X size={20} />
          </button>
        </div>

        <div className={styles.body}>
          {isLoading ? (
            <p className={styles.emptyText}>Loading form...</p>
          ) : (
            <>
              <div className={fieldStyles.fieldList}>
                {fields.map((field) => (
                  <div key={field.id} className={fieldStyles.fieldCard}>
                    <div className={fieldStyles.fieldMainRow}>
                      <input
                        id={`label-${field.id}`}
                        type="text"
                        className={fieldStyles.compactInput}
                        placeholder="Field label"
                        value={field.label}
                        onChange={(e) => updateField(field.id, { label: e.target.value })}
                        aria-label="Field label"
                      />
                      <select
                        id={`type-${field.id}`}
                        className={fieldStyles.compactInput}
                        value={field.type}
                        aria-label="Input type"
                        onChange={(e) => {
                          const type = e.target.value as TechnicalFieldType
                          updateField(field.id, {
                            type,
                            options:
                              type === 'select' || type === 'multi_select'
                                ? field.options.length
                                  ? field.options
                                  : ['']
                                : [],
                          })
                        }}
                      >
                        {Object.entries(FIELD_TYPE_LABELS).map(([value, label]) => (
                          <option key={value} value={value}>
                            {label}
                          </option>
                        ))}
                      </select>
                      <label className={fieldStyles.requiredCell} title="Required">
                        <input
                          type="checkbox"
                          checked={field.isRequired}
                          onChange={(e) =>
                            updateField(field.id, { isRequired: e.target.checked })
                          }
                        />
                        <span>Required</span>
                      </label>
                      <div className={fieldStyles.removeCell}>
                        <button
                          type="button"
                          className={styles.removeRowBtn}
                          onClick={() => removeField(field.id)}
                          aria-label="Remove field"
                        >
                          <Trash2 size={15} />
                        </button>
                      </div>
                    </div>

                    {(field.type === 'select' || field.type === 'multi_select') && (
                      <div className={fieldStyles.optionsBlock}>
                        <span className={fieldStyles.optionsLabel}>Options</span>
                        <div className={fieldStyles.customValues}>
                          {field.options.map((option, optionIndex) => (
                            <div key={optionIndex} className={fieldStyles.customRow}>
                              <input
                                ref={(el) => {
                                  if (!optionInputRefs.current[field.id]) {
                                    optionInputRefs.current[field.id] = []
                                  }
                                  optionInputRefs.current[field.id][optionIndex] = el
                                }}
                                type="text"
                                placeholder={`Option ${optionIndex + 1}`}
                                value={option}
                                onChange={(e) =>
                                  updateOption(field.id, optionIndex, e.target.value)
                                }
                                onKeyDown={(e) =>
                                  handleOptionKeyDown(field.id, optionIndex, e, field.options)
                                }
                              />
                              {field.options.length > 1 && (
                                <div className={fieldStyles.removeCell}>
                                  <button
                                    type="button"
                                    className={styles.removeRowBtn}
                                    onClick={() => removeOption(field.id, optionIndex)}
                                    aria-label="Remove option"
                                  >
                                    <X size={16} />
                                  </button>
                                </div>
                              )}
                              {field.options.length <= 1 && <div />}
                            </div>
                          ))}
                          <button
                            type="button"
                            className={styles.addValueBtn}
                            onClick={() => addOption(field.id)}
                          >
                            <Plus size={14} />
                            Add option
                          </button>
                        </div>
                      </div>
                    )}
                  </div>
                ))}

                {!fields.length && (
                  <p className={styles.emptyText}>
                    No fields yet. Add text, textarea, select, or multi-select inputs.
                  </p>
                )}
              </div>

              <div className={fieldStyles.toolbar}>
                {(onGenerateClick ?? onGenerate) && (
                  <button
                    type="button"
                    className={aiStyles.aiBtn}
                    onClick={onGenerateClick ?? onGenerate}
                    disabled={isLoading || isSaving || isGenerating}
                  >
                    <Sparkles size={16} />
                    {isGenerating ? 'Generating…' : 'Generate with AI'}
                  </button>
                )}
                <button type="button" className={styles.addBtn} onClick={addField}>
                  <Plus size={18} />
                  Add field
                </button>
              </div>
            </>
          )}

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

          <div className={styles.actions}>
            <button
              type="button"
              className={styles.cancelBtn}
              onClick={onClose}
              disabled={isSaving || isGenerating}
            >
              Cancel
            </button>
            <button
              type="button"
              className={styles.submitBtn}
              onClick={onSave}
              disabled={!canSave}
            >
              {isSaving ? 'Saving…' : 'Save form'}
            </button>
          </div>
        </div>
      </div>
    </div>
  ,
  document.body,
  )
}
