import { useEffect, useRef, useState } from 'react'
import { createPortal } from 'react-dom'
import {
  BUSINESS_PRIMARY_COLOR_IDS,
  BUSINESS_PRIMARY_COLOR_PALETTE,
  type BusinessPrimaryColorId,
} from '../utils/businessPrimaryColors'
import styles from './PrimaryColorSwatchControl.module.css'

interface PrimaryColorSwatchControlProps {
  value: BusinessPrimaryColorId
  onChange: (value: BusinessPrimaryColorId) => void
  disabled?: boolean
}

type PopoverPosition = {
  top: number
  left: number
}

export function PrimaryColorSwatchControl({
  value,
  onChange,
  disabled = false,
}: PrimaryColorSwatchControlProps) {
  const [open, setOpen] = useState(false)
  const [popoverPos, setPopoverPos] = useState<PopoverPosition | null>(null)
  const wrapRef = useRef<HTMLDivElement>(null)
  const popoverRef = useRef<HTMLDivElement>(null)
  const triggerRef = useRef<HTMLButtonElement>(null)

  const tokens = BUSINESS_PRIMARY_COLOR_PALETTE[value]

  function updatePopoverPosition() {
    const rect = triggerRef.current?.getBoundingClientRect()
    if (!rect) return

    setPopoverPos({
      top: rect.bottom + 8,
      left: rect.left + rect.width / 2,
    })
  }

  function toggleOpen() {
    if (disabled) return

    if (open) {
      setOpen(false)
      return
    }

    updatePopoverPosition()
    setOpen(true)
  }

  function selectColor(colorId: BusinessPrimaryColorId) {
    if (colorId !== value) {
      onChange(colorId)
    }
    setOpen(false)
  }

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

    function handleClickOutside(e: MouseEvent) {
      const target = e.target as Node
      if (wrapRef.current?.contains(target)) return
      if (popoverRef.current?.contains(target)) return
      setOpen(false)
    }

    function handleEscape(e: KeyboardEvent) {
      if (e.key === 'Escape') setOpen(false)
    }

    function handleReposition() {
      updatePopoverPosition()
    }

    document.addEventListener('mousedown', handleClickOutside)
    document.addEventListener('keydown', handleEscape)
    window.addEventListener('resize', handleReposition)
    window.addEventListener('scroll', handleReposition, true)

    return () => {
      document.removeEventListener('mousedown', handleClickOutside)
      document.removeEventListener('keydown', handleEscape)
      window.removeEventListener('resize', handleReposition)
      window.removeEventListener('scroll', handleReposition, true)
    }
  }, [open])

  return (
    <div className={styles.wrap} ref={wrapRef}>
      <button
        ref={triggerRef}
        type="button"
        className={`${styles.trigger} ${open ? styles.triggerOpen : ''}`}
        onClick={toggleOpen}
        disabled={disabled}
        aria-label={`Dashboard primary color: ${tokens.label}`}
        aria-haspopup="listbox"
        aria-expanded={open}
        title={`Theme: ${tokens.label}`}
      >
        <span
          className={styles.swatchDot}
          style={{ backgroundColor: tokens.primary }}
          aria-hidden="true"
        />
      </button>

      {open &&
        popoverPos &&
        createPortal(
          <div
            ref={popoverRef}
            className={styles.popover}
            role="listbox"
            aria-label="Choose primary color"
            style={{
              top: popoverPos.top,
              left: popoverPos.left,
            }}
          >
            {BUSINESS_PRIMARY_COLOR_IDS.map((colorId) => {
              const option = BUSINESS_PRIMARY_COLOR_PALETTE[colorId]
              const selected = colorId === value

              return (
                <button
                  key={colorId}
                  type="button"
                  role="option"
                  aria-selected={selected}
                  aria-label={option.label}
                  className={`${styles.option} ${selected ? styles.optionSelected : ''}`}
                  onClick={() => selectColor(colorId)}
                >
                  <span
                    className={styles.optionDot}
                    style={{ backgroundColor: option.primary }}
                    aria-hidden="true"
                  />
                </button>
              )
            })}
          </div>,
          document.body,
        )}
    </div>
  )
}
