import React from 'react'
import type { PresetNode } from './types.js'

interface PresetAssetTreeProps {
  assignedNodeId?: string
  nodes: PresetNode[]
  selectedNodeId?: string
  onSelect: (node: PresetNode) => void
}

interface TreeItem {
  node: PresetNode
  children: TreeItem[]
}

function compareNodes(left: PresetNode, right: PresetNode) {
  return left.sort_order - right.sort_order || left.name.localeCompare(right.name)
}

function buildTree(nodes: PresetNode[]) {
  const byParent = new Map<string | null, PresetNode[]>()
  for (const node of nodes) {
    const siblings = byParent.get(node.parent_id) ?? []
    siblings.push(node)
    byParent.set(node.parent_id, siblings)
  }

  function build(parentId: string | null): TreeItem[] {
    return (byParent.get(parentId) ?? [])
      .sort(compareNodes)
      .map((node) => ({ node, children: build(node.id) }))
  }

  return build(null)
}

export function PresetAssetTree({
  assignedNodeId,
  nodes,
  selectedNodeId,
  onSelect
}: PresetAssetTreeProps) {
  const tree = React.useMemo(() => buildTree(nodes), [nodes])

  if (tree.length === 0) return <p className="empty">This CA library has no presets.</p>

  return (
    <div className="asset-tree">
      {tree.map((item) => (
        <AssetTreeItem
          assignedNodeId={assignedNodeId}
          item={item}
          key={item.node.id}
          selectedNodeId={selectedNodeId}
          onSelect={onSelect}
        />
      ))}
    </div>
  )
}

function AssetTreeItem({
  assignedNodeId,
  item,
  selectedNodeId,
  onSelect
}: {
  assignedNodeId?: string
  item: TreeItem
  selectedNodeId?: string
  onSelect: (node: PresetNode) => void
}) {
  const [open, setOpen] = React.useState(true)
  const selected = item.node.id === selectedNodeId
  const assigned = item.node.id === assignedNodeId

  return (
    <div className="asset-tree-item">
      <div className={`asset-tree-row${selected ? ' selected' : ''}${assigned ? ' assigned' : ''}`}>
        <button
          aria-label={item.children.length ? `${open ? 'Collapse' : 'Expand'} ${item.node.name}` : `${item.node.name} has no children`}
          className="asset-tree-arrow"
          disabled={!item.children.length}
          type="button"
          onClick={() => setOpen((current) => !current)}
        >
          {item.children.length ? (open ? '▾' : '▸') : '·'}
        </button>
        <button className="asset-tree-select" type="button" onClick={() => onSelect(item.node)}>
          <strong>{item.node.name}</strong>
          <small>
            {item.node.kind}
            {assigned ? ' · current' : ''}
          </small>
          {item.node.description ? <span>{item.node.description}</span> : null}
        </button>
      </div>
      {open && item.children.length ? (
        <div className="asset-tree-children">
          {item.children.map((child) => (
            <AssetTreeItem
              assignedNodeId={assignedNodeId}
              item={child}
              key={child.node.id}
              selectedNodeId={selectedNodeId}
              onSelect={onSelect}
            />
          ))}
        </div>
      ) : null}
    </div>
  )
}
