import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'
import { createPortal } from 'react-dom'
import { collectSkillLeavesFromTree, buildSkillCatalogTree } from '../utils/skillCatalogTree'
import SkillTreePickerPanel from './SkillTreePickerPanel'

const PANEL_MAX_HEIGHT = 360
const PANEL_MIN_HEIGHT = 140
const PANEL_Z_INDEX = 1100

function normId(id) {
  return String(id)
}

/**
 * Mehrfachauswahl Fähigkeiten mit hierarchischer Treeview („Alle“) und Pfad-Suche.
 */
export default function SkillTreeMultiSelect({
  value = [],
  onChange,
  skills = [],
  placeholder = 'Fähigkeit suchen …',
  browseLabel = '▼ Katalog',
  emptyHint = 'Keine Treffer',
  className = '',
  usePortal = true,
}) {
  const [query, setQuery] = useState('')
  const [open, setOpen] = useState(false)
  const [browseTree, setBrowseTree] = useState(false)
  const [panelStyle, setPanelStyle] = useState(null)
  const rootRef = useRef(null)
  const fieldRef = useRef(null)
  const panelRef = useRef(null)

  const tree = useMemo(() => buildSkillCatalogTree(skills), [skills])
  const selectedSet = useMemo(() => new Set(value.map(normId)), [value])

  const leaves = useMemo(() => collectSkillLeavesFromTree(tree, value), [tree, value])

  const selectedLabels = useMemo(() => {
    return value.map((id) => {
      const leaf = leaves.find((l) => normId(l.id) === normId(id)) || leaves.find(() => false)
      const fromSkills = skills.find((s) => normId(s.id) === normId(id))
      return leaf?.pathLabel || fromSkills?.name || `#${id}`
    })
  }, [value, leaves, skills])

  const addId = useCallback(
    (id) => {
      const sid = normId(id)
      if (selectedSet.has(sid)) return
      onChange([...value, id])
      setQuery('')
      setBrowseTree(false)
    },
    [value, onChange, selectedSet]
  )

  const removeAt = useCallback(
    (idx) => {
      onChange(value.filter((_, i) => i !== idx))
    },
    [value, onChange]
  )

  useEffect(() => {
    const onDoc = (e) => {
      const t = e.target
      if (rootRef.current?.contains(t) || panelRef.current?.contains(t)) return
      setOpen(false)
      setBrowseTree(false)
    }
    document.addEventListener('mousedown', onDoc)
    return () => document.removeEventListener('mousedown', onDoc)
  }, [])

  const updatePanelPosition = useCallback(() => {
    const anchor = fieldRef.current
    if (!anchor) return
    const rect = anchor.getBoundingClientRect()
    const gap = 4
    const margin = 12
    const spaceBelow = window.innerHeight - rect.bottom - gap - margin
    const spaceAbove = rect.top - gap - margin
    const openUp = spaceBelow < PANEL_MIN_HEIGHT && spaceAbove > spaceBelow
    const available = Math.max(0, openUp ? spaceAbove : spaceBelow)
    const maxHeight = Math.min(PANEL_MAX_HEIGHT, Math.max(PANEL_MIN_HEIGHT, available))
    const top = openUp ? Math.max(margin, rect.top - gap - maxHeight) : rect.bottom + gap

    setPanelStyle({
      position: 'fixed',
      left: rect.left,
      width: rect.width,
      top,
      maxHeight,
      zIndex: PANEL_Z_INDEX,
    })
  }, [])

  useLayoutEffect(() => {
    if (!open || !usePortal) {
      setPanelStyle(null)
      return undefined
    }
    updatePanelPosition()
    window.addEventListener('resize', updatePanelPosition)
    window.addEventListener('scroll', updatePanelPosition, true)
    return () => {
      window.removeEventListener('resize', updatePanelPosition)
      window.removeEventListener('scroll', updatePanelPosition, true)
    }
  }, [open, usePortal, updatePanelPosition, query, browseTree, value.length])

  const showTree = browseTree || !query.trim()

  const panelContent = showTree ? (
    <SkillTreePickerPanel
      skills={skills}
      excludeIds={value}
      searchQuery={query}
      onPickSkill={(id) => addId(id)}
      pickMode="multi"
    />
  ) : (
    <ul className="multiselect-combo__list" role="listbox">
      {leaves.filter((l) => l.pathLabel.toLowerCase().includes(query.trim().toLowerCase())).length === 0 ? (
        <li className="multiselect-combo__empty">{emptyHint}</li>
      ) : (
        leaves
          .filter((l) => l.pathLabel.toLowerCase().includes(query.trim().toLowerCase()))
          .map((l) => (
            <li key={normId(l.id)}>
              <button
                type="button"
                className="multiselect-combo__opt skill-tree__pick--path"
                onMouseDown={(e) => e.preventDefault()}
                onClick={() => addId(l.id)}
              >
                <span className="skill-tree__pick-name">{l.label}</span>
                <span className="skill-tree__pick-path">{l.pathLabel}</span>
              </button>
            </li>
          ))
      )}
    </ul>
  )

  const dropdownPanel =
    open && (usePortal ? panelStyle : true) ? (
      <div
        ref={panelRef}
        className={
          'skill-tree-multiselect__panel' + (usePortal ? ' skill-tree-multiselect__panel--portal' : '')
        }
        style={usePortal ? panelStyle : undefined}
      >
        {panelContent}
      </div>
    ) : null

  return (
    <div className={`multiselect-combo skill-tree-multiselect ${className}`.trim()} ref={rootRef}>
      <div className="multiselect-combo__chips">
        {value.map((id, idx) => (
          <button
            key={`${normId(id)}-${idx}`}
            type="button"
            className="multiselect-combo__chip"
            onClick={() => removeAt(idx)}
            title="Entfernen"
          >
            <span>{selectedLabels[idx]}</span>
            <span className="multiselect-combo__chip-x" aria-hidden>
              ×
            </span>
          </button>
        ))}
      </div>
      <div className="multiselect-combo__field" ref={fieldRef}>
        <input
          type="text"
          className="form-input multiselect-combo__input"
          placeholder={placeholder}
          value={query}
          onChange={(e) => {
            setQuery(e.target.value)
            setOpen(true)
            setBrowseTree(false)
          }}
          onFocus={() => setOpen(true)}
          autoComplete="off"
          aria-expanded={open}
        />
        <button
          type="button"
          className="btn multiselect-combo__browse"
          title="Katalog als Baum"
          onClick={() => {
            setOpen(true)
            setBrowseTree(true)
            setQuery('')
          }}
        >
          {browseLabel}
        </button>
      </div>
      {!usePortal && dropdownPanel}
      {usePortal && dropdownPanel ? createPortal(dropdownPanel, document.body) : null}
    </div>
  )
}
