import { useEffect, useMemo, useState } from 'react'
import { useCategories } from '../contexts/CategoryContext.jsx'
import { useFiles } from '../contexts/FilesContext.jsx'

// 把节点的祖先路径拼成 "IPD 集成产品开发 / 战略规划 / 市场扫描"
export function getNodePath(nodeId, flat) {
  if (nodeId == null) return ''
  const idMap = new Map(flat.map(n => [n.id, n]))
  const segs = []
  let cur = idMap.get(nodeId)
  while (cur) {
    segs.unshift(cur.label)
    cur = cur.parent_id != null ? idMap.get(cur.parent_id) : null
  }
  return segs.join(' / ')
}

// 单一节点行（不含 hover 操作按钮，纯展示 + 选中态）
function PickerNode({ node, depth, expandedMap, toggle, onPick, selectedId, fileCountMap, matchedIds, searchActive, ancestorArchived }) {
  const hasChildren = node.children && node.children.length > 0
  const expanded = !!expandedMap[node.id] || (searchActive && matchedIds.has(node.id))
  const active = selectedId === node.id
  const matched = !searchActive || matchedIds.has(node.id)
  if (!matched) return null
  const fileCount = fileCountMap.get(node.id) || 0
  // archived：本身或任一祖先在 archived，全部不可选
  const archived = node.status === 'archived' || ancestorArchived
  return (
    <div>
      <div
        onClick={() => {
          // archived 节点：折叠仍可用，但不能被选中
          if (hasChildren) toggle(node.id)
          if (!archived) onPick(node)
        }}
        className={[
          'flex items-center gap-1.5 px-2 py-1.5 rounded-md text-[13px] select-none',
          archived ? 'cursor-not-allowed opacity-50 text-gray-400'
                   : (active ? 'bg-brand-50 text-brand-700 font-medium cursor-pointer'
                             : 'text-gray-700 hover:bg-gray-50 cursor-pointer')
        ].join(' ')}
        style={{ paddingLeft: 8 + depth * 14 }}
        title={archived ? '该节点已归档，不可选中' : ''}
      >
        {hasChildren ? (
          <span className={`w-3 text-gray-400 inline-block transition-transform ${expanded ? 'rotate-90' : ''}`}>▸</span>
        ) : (
          <span className="w-3 text-gray-200">•</span>
        )}
        <span className="truncate flex-1">
          {node.label}
          {archived && <span className="ml-2 text-[10px] px-1 py-0.5 rounded bg-gray-100 text-gray-500">已归档</span>}
        </span>
        {fileCount > 0 && (
          <span className="text-[11px] px-1.5 py-0.5 rounded bg-brand-50 text-brand-700">{fileCount} 文件</span>
        )}
      </div>
      {hasChildren && expanded && node.children.map(c => (
        <PickerNode
          key={c.id}
          node={c}
          depth={depth + 1}
          expandedMap={expandedMap}
          toggle={toggle}
          onPick={onPick}
          selectedId={selectedId}
          fileCountMap={fileCountMap}
          matchedIds={matchedIds}
          searchActive={searchActive}
          ancestorArchived={archived}
        />
      ))}
    </div>
  )
}

export default function NodePickerModal({ open, initialNodeId = null, onClose, onConfirm }) {
  const { tree, flat } = useCategories()
  const { files } = useFiles()

  const [selectedId, setSelectedId] = useState(initialNodeId)
  const [keyword, setKeyword] = useState('')
  const [expandedMap, setExpandedMap] = useState(() => Object.fromEntries(tree.map(n => [n.id, true])))

  useEffect(() => {
    if (open) {
      setSelectedId(initialNodeId)
      setKeyword('')
      // 如果传入了 initialNodeId，把它的祖先全部展开
      const idMap = new Map(flat.map(n => [n.id, n]))
      const expand = { ...Object.fromEntries(tree.map(n => [n.id, true])) }
      let cur = initialNodeId != null ? idMap.get(initialNodeId) : null
      while (cur) { expand[cur.id] = true; cur = cur.parent_id != null ? idMap.get(cur.parent_id) : null }
      setExpandedMap(expand)
    }
  }, [open, initialNodeId, flat, tree])

  // 每个节点（含子孙）下的文件总数，用于显示 badge
  const fileCountMap = useMemo(() => {
    const map = new Map()
    // 直接挂在节点上的
    files.forEach(f => map.set(f.category_id, (map.get(f.category_id) || 0) + 1))
    // 把子孙的累加到祖先上
    const idMap = new Map(flat.map(n => [n.id, n]))
    const cumulative = new Map(map)
    flat.forEach(n => {
      const own = map.get(n.id) || 0
      if (own === 0) return
      let p = n.parent_id != null ? idMap.get(n.parent_id) : null
      while (p) {
        cumulative.set(p.id, (cumulative.get(p.id) || 0) + own)
        p = p.parent_id != null ? idMap.get(p.parent_id) : null
      }
    })
    return cumulative
  }, [files, flat])

  const { matchedIds, searchActive } = useMemo(() => {
    const k = keyword.trim().toLowerCase()
    if (!k) return { matchedIds: new Set(), searchActive: false }
    const idMap = new Map(flat.map(n => [n.id, n]))
    const set = new Set()
    flat.forEach(n => {
      if (n.label.toLowerCase().includes(k)) {
        let cur = n
        while (cur) { set.add(cur.id); cur = cur.parent_id != null ? idMap.get(cur.parent_id) : null }
        const queue = [n.id]
        while (queue.length) {
          const pid = queue.shift()
          flat.filter(x => x.parent_id === pid).forEach(c => { set.add(c.id); queue.push(c.id) })
        }
      }
    })
    return { matchedIds: set, searchActive: true }
  }, [keyword, flat])

  const toggle = (id) => setExpandedMap(m => ({ ...m, [id]: !m[id] }))

  const selectedPath = useMemo(() => getNodePath(selectedId, flat), [selectedId, flat])
  const selectedFileCount = selectedId != null ? (fileCountMap.get(selectedId) || 0) : 0

  if (!open) return null

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/30" onClick={onClose}>
      <div
        className="bg-white rounded-xl shadow-xl w-[680px] max-h-[80vh] flex flex-col"
        onClick={e => e.stopPropagation()}
      >
        {/* 头部 */}
        <div className="px-5 py-4 border-b border-gray-100 flex items-center justify-between">
          <div>
            <div className="text-[15px] font-semibold text-gray-900">关联流程节点</div>
            <div className="text-[12px] text-gray-500 mt-0.5">从流程架构中选择 1 个节点。该节点（含子孙）下挂载的文件可作为 Skill 上下文。</div>
          </div>
          <button onClick={onClose} className="text-gray-400 hover:text-gray-600 text-[18px] leading-none">×</button>
        </div>

        {/* 搜索 */}
        <div className="px-5 pt-3 pb-2">
          <input
            value={keyword}
            onChange={e => setKeyword(e.target.value)}
            placeholder="搜索节点（如：IPD、销售、根因）..."
            className="w-full px-3 py-2 text-[13px] border border-gray-200 rounded-md focus:outline-none focus:border-brand-400"
          />
        </div>

        {/* 树主体 */}
        <div className="flex-1 overflow-y-auto px-2 pb-2 scrollbar-thin">
          {tree.map(n => (
            <PickerNode
              key={n.id}
              node={n}
              depth={0}
              expandedMap={expandedMap}
              toggle={toggle}
              onPick={(node) => setSelectedId(node.id)}
              selectedId={selectedId}
              fileCountMap={fileCountMap}
              matchedIds={matchedIds}
              searchActive={searchActive}
              ancestorArchived={false}
            />
          ))}
        </div>

        {/* 已选节点 + 操作 */}
        <div className="px-5 py-3 border-t border-gray-100 bg-gray-50/60">
          <div className="text-[12px] text-gray-500 mb-1">已选节点</div>
          <div className="flex items-center justify-between gap-3">
            <div className="text-[13px] text-gray-800 truncate">
              {selectedId != null ? (
                <>
                  <span className="text-brand-700 font-medium">{selectedPath}</span>
                  <span className="ml-2 text-[11px] text-gray-500">该节点（含子孙）下共 {selectedFileCount} 个文件</span>
                </>
              ) : (
                <span className="text-gray-400">未选择</span>
              )}
            </div>
            <div className="flex items-center gap-2 flex-shrink-0">
              <button onClick={onClose} className="px-3 py-1.5 text-[13px] rounded-md text-gray-600 border border-gray-200 hover:bg-gray-50">取消</button>
              <button
                onClick={() => onConfirm(selectedId)}
                disabled={selectedId == null}
                className="px-3.5 py-1.5 text-[13px] rounded-md text-white bg-brand-600 hover:bg-brand-700 disabled:bg-gray-300 disabled:cursor-not-allowed"
              >确认关联</button>
            </div>
          </div>
        </div>
      </div>
    </div>
  )
}
