import { useState, useMemo, useCallback } from 'react'
import { Search, Plus, ChevronDown, ChevronRight, X, LayoutGrid, GripVertical, Globe } from 'lucide-react'
import { getDeviceRenderConfig, CATEGORY_LABELS, CATEGORY_ORDER } from '../nodes/deviceRegistry'
import type { DeviceTypeResponse, DeviceTypeCreate } from '@/types'
import { deviceTypesApi } from '@/api'

interface DeviceToolbarProps {
  deviceTypes: DeviceTypeResponse[]
  onDeviceTypesChange: () => void
}

export function DeviceToolbar({ deviceTypes, onDeviceTypesChange }: DeviceToolbarProps) {
  const [search, setSearch] = useState('')
  const [collapsedCategories, setCollapsedCategories] = useState<Set<string>>(new Set())
  const [showAddForm, setShowAddForm] = useState(false)
  const [newType, setNewType] = useState<DeviceTypeCreate>({ slug: '', label: '', category: 'network' })
  const [addError, setAddError] = useState<string | null>(null)
  const [addLoading, setAddLoading] = useState(false)

  const filteredByCategory = useMemo(() => {
    const lower = search.toLowerCase()
    const filtered = search
      ? deviceTypes.filter(dt => dt.label.toLowerCase().includes(lower) || dt.slug.toLowerCase().includes(lower))
      : deviceTypes

    const grouped: Record<string, DeviceTypeResponse[]> = {}
    for (const dt of filtered) {
      if (!grouped[dt.category]) grouped[dt.category] = []
      grouped[dt.category].push(dt)
    }
    return grouped
  }, [deviceTypes, search])

  const toggleCategory = useCallback((cat: string) => {
    setCollapsedCategories(prev => {
      const next = new Set(prev)
      if (next.has(cat)) next.delete(cat)
      else next.add(cat)
      return next
    })
  }, [])

  const handleDragStart = useCallback((e: React.DragEvent, deviceType: DeviceTypeResponse) => {
    e.dataTransfer.setData('application/reactflow-device', JSON.stringify({
      slug: deviceType.slug,
      label: deviceType.label,
      category: deviceType.category,
    }))
    e.dataTransfer.effectAllowed = 'move'
  }, [])

  const handleAddType = useCallback(async () => {
    if (!newType.slug || !newType.label) {
      setAddError('Slug and label are required')
      return
    }
    setAddLoading(true)
    setAddError(null)
    try {
      await deviceTypesApi.create(newType)
      setNewType({ slug: '', label: '', category: 'network' })
      setShowAddForm(false)
      onDeviceTypesChange()
    } catch (err: unknown) {
      const msg = err instanceof Error ? err.message : 'Failed to create device type'
      setAddError(msg)
    } finally {
      setAddLoading(false)
    }
  }, [newType, onDeviceTypesChange])

  return (
    <div className="flex h-full w-[200px] flex-col border-r border-default bg-sidebar">
      <div className="relative p-2">
        <Search size={14} className="absolute left-4 top-1/2 -translate-y-1/2 text-muted-foreground" />
        <input
          type="text"
          placeholder="Search devices..."
          value={search}
          onChange={e => setSearch(e.target.value)}
          className="w-full rounded-md border border-default bg-input pl-8 pr-2 py-1.5 text-xs text-primary placeholder:text-muted-foreground focus:border-accent focus:outline-none"
        />
      </div>

      <div className="flex-1 overflow-y-auto px-2 pb-2">
        {CATEGORY_ORDER.map(cat => {
          const items = filteredByCategory[cat] || []
          const isCloud = cat === 'cloud'
          const ispMatchesSearch = !search || 'isp'.includes(search.toLowerCase()) || 'internet service provider'.includes(search.toLowerCase())
          const showIsp = isCloud && ispMatchesSearch
          if (!items.length && !showIsp) return null
          const collapsed = collapsedCategories.has(cat)
          const totalCount = items.length + (showIsp ? 1 : 0)

          return (
            <div key={cat} className="mb-1">
              <button
                onClick={() => toggleCategory(cat)}
                className="flex w-full items-center gap-1 rounded px-1 py-1 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground hover:text-primary"
              >
                {collapsed ? <ChevronRight size={12} /> : <ChevronDown size={12} />}
                {CATEGORY_LABELS[cat] || cat}
                <span className="ml-auto text-[10px] font-normal">{totalCount}</span>
              </button>
              {!collapsed && (
                <div className="flex flex-col gap-0.5">
                  {items.map(dt => {
                    const { icon: Icon, color } = getDeviceRenderConfig(dt.slug, dt.category)
                    return (
                      <div
                        key={dt.id}
                        draggable
                        onDragStart={e => handleDragStart(e, dt)}
                        className="flex cursor-grab items-center gap-2 rounded px-2 py-1.5 text-xs text-primary hover:bg-elevated active:cursor-grabbing active:scale-[0.98] transition-transform"
                      >
                        <GripVertical size={12} className="shrink-0 text-muted-foreground/50" />
                        <Icon size={14} style={{ color }} />
                        <span>{dt.label}</span>
                      </div>
                    )
                  })}
                  {showIsp && (
                    <div
                      draggable
                      onDragStart={e => {
                        e.dataTransfer.setData('application/reactflow-device', JSON.stringify({
                          slug: 'isp',
                          label: 'ISP',
                          category: 'cloud',
                        }))
                        e.dataTransfer.effectAllowed = 'move'
                      }}
                      className="flex cursor-grab items-center gap-2 rounded px-2 py-1.5 text-xs text-primary hover:bg-elevated active:cursor-grabbing active:scale-[0.98] transition-transform"
                    >
                      <GripVertical size={12} className="shrink-0 text-muted-foreground/50" />
                      <Globe size={14} style={{ color: 'var(--color-accent)' }} />
                      <span>ISP</span>
                    </div>
                  )}
                </div>
              )}
            </div>
          )
        })}
      </div>

      {/* Grouping section */}
      <div className="mb-1 mt-2 border-t border-default pt-2">
        <div className="flex items-center gap-1 px-1 py-1 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground">
          Grouping
        </div>
        <div className="flex flex-col gap-0.5">
          {[
            { slug: 'subnet', label: 'Subnet', color: '#60a5fa' },
            { slug: 'vlan',   label: 'VLAN',   color: '#a78bfa' },
            { slug: 'site',   label: 'Site',   color: '#34d399' },
            { slug: 'dmz',    label: 'DMZ',    color: '#f87171' },
          ].map(item => (
            <div
              key={item.slug}
              draggable
              onDragStart={e => {
                e.dataTransfer.setData('application/reactflow-group', JSON.stringify({ slug: item.slug, label: item.label }))
                e.dataTransfer.effectAllowed = 'move'
              }}
              className="flex cursor-grab items-center gap-2 rounded px-2 py-1.5 text-xs text-primary hover:bg-elevated active:cursor-grabbing active:scale-[0.98] transition-transform"
            >
              <GripVertical size={12} className="shrink-0 text-muted-foreground/50" />
              <LayoutGrid size={14} style={{ color: item.color }} />
              <span>{item.label}</span>
            </div>
          ))}
        </div>
      </div>

      <div className="border-t border-default p-2">
        {!showAddForm ? (
          <button
            onClick={() => setShowAddForm(true)}
            className="flex w-full items-center justify-center gap-1 rounded border border-default px-2 py-1.5 text-xs text-muted-foreground hover:border-hover hover:text-primary"
          >
            <Plus size={12} />
            Custom Type
          </button>
        ) : (
          <div className="flex flex-col gap-1.5">
            <div className="flex items-center justify-between">
              <span className="text-[10px] font-semibold uppercase tracking-wider text-muted-foreground">New Type</span>
              <button onClick={() => { setShowAddForm(false); setAddError(null) }} className="text-muted-foreground hover:text-primary">
                <X size={12} />
              </button>
            </div>
            <input
              placeholder="slug (e.g. pacs-server)"
              value={newType.slug}
              onChange={e => setNewType(prev => ({ ...prev, slug: e.target.value.toLowerCase().replace(/[^a-z0-9-]/g, '') }))}
              className="rounded border border-default bg-input px-2 py-1 text-xs text-primary placeholder:text-muted-foreground focus:border-accent focus:outline-none"
            />
            <input
              placeholder="Label (e.g. PACS Server)"
              value={newType.label}
              onChange={e => setNewType(prev => ({ ...prev, label: e.target.value }))}
              className="rounded border border-default bg-input px-2 py-1 text-xs text-primary placeholder:text-muted-foreground focus:border-accent focus:outline-none"
            />
            <select
              value={newType.category}
              onChange={e => setNewType(prev => ({ ...prev, category: e.target.value }))}
              className="rounded border border-default bg-input px-2 py-1 text-xs text-primary focus:border-accent focus:outline-none"
            >
              {CATEGORY_ORDER.map(c => (
                <option key={c} value={c}>{CATEGORY_LABELS[c]}</option>
              ))}
            </select>
            {addError && <p className="text-[10px] text-red-400">{addError}</p>}
            <button
              onClick={handleAddType}
              disabled={addLoading}
              className="rounded bg-accent px-2 py-1 text-xs font-medium text-white hover:bg-accent/90 disabled:opacity-50"
            >
              {addLoading ? 'Adding...' : 'Add Type'}
            </button>
          </div>
        )}
      </div>
    </div>
  )
}
