'use client'

import React, { useMemo } from 'react'
import { Node, Handle, Position } from '@xyflow/react'
import { Badge } from '@/components/ui/badge'
import { FileCode, FileX } from 'lucide-react'
import { AdaptiveGraph } from '@/components/features/adaptive-graph'

// 节点数据类型
interface GraphNodeData {
  id: string
  path: string
  fileName: string
  fileTypeId: string
  fileTypeName: string
  summary: string | null
  dependencyCount: number
  isDeleted: boolean
}

// 组件 Props
interface FileDependencyGraphProps {
  nodes: GraphNodeData[]
  edges: Array<{ source: string; target: string; label?: string }>
  onNodeClick?: (node: GraphNodeData) => void
}

// 自定义节点组件
const CustomNode = ({ data }: { data: GraphNodeData & { isHighlighted?: boolean; isDimmed?: boolean } }) => {
  const bgColor = data.isDeleted
    ? 'bg-red-50 dark:bg-red-950/20'
    : data.isHighlighted
    ? 'bg-blue-50 dark:bg-blue-950/50'
    : data.isDimmed
    ? 'bg-gray-50 dark:bg-gray-900/30'
    : 'bg-white dark:bg-gray-800'

  const borderColor = data.isDeleted
    ? 'border-red-300 dark:border-red-700'
    : data.isHighlighted
    ? 'border-blue-500 dark:border-blue-400'
    : 'border-gray-200 dark:border-gray-700'

  const opacity = data.isDimmed ? 'opacity-40' : 'opacity-100'

  return (
    <div
      className={`px-3 py-2 rounded-lg border-2 shadow-sm transition-all ${bgColor} ${borderColor} ${opacity} min-w-[180px] max-w-[220px]`}
    >
      {/* Handle 组件用于连接边，没有Handle看不见连边，!opacity-0用来隐藏卡片上用来连接的小点 */}
      <Handle type="target" position={Position.Top} className="!opacity-0" />
      <div className="flex items-start gap-2">
        {data.isDeleted ? (
          <FileX className="h-4 w-4 text-red-500 flex-shrink-0 mt-0.5" />
        ) : (
          <FileCode className="h-4 w-4 text-blue-500 flex-shrink-0 mt-0.5" />
        )}
        <div className="flex-1 min-w-0">
          <div className="font-medium text-sm truncate" title={data.fileName}>
            {data.fileName}
          </div>
          <div className="text-xs text-muted-foreground truncate" title={data.path}>
            {data.path}
          </div>
          <div className="flex items-center gap-1 mt-1">
            <Badge variant="outline" className="text-xs px-1 py-0">
              {data.fileTypeName}
            </Badge>
            {data.dependencyCount > 0 && (
              <Badge variant="secondary" className="text-xs px-1 py-0">
                {data.dependencyCount} 依赖
              </Badge>
            )}
            {data.isDeleted && (
              <Badge variant="destructive" className="text-xs px-1 py-0">
                已删除
              </Badge>
            )}
          </div>
        </div>
      </div>
      {/* Handle 组件用于连接边，没有Handle看不见连边，!opacity-0用来隐藏卡片上用来连接的小点 */}
      <Handle type="source" position={Position.Bottom} className="!opacity-0" />
    </div>
  )
}

// 节点类型定义
const nodeTypes = {
  custom: CustomNode,
}

export function FileDependencyGraph({ nodes: rawNodes, edges: rawEdges, onNodeClick }: FileDependencyGraphProps) {
  // 构建依赖关系映射
  const dependencyMap = useMemo(() => {
    const map = new Map<string, Set<string>>()
    const reverseDependencyMap = new Map<string, Set<string>>()

    rawEdges.forEach((edge) => {
      // 正向依赖：source 依赖 target
      if (!map.has(edge.source)) {
        map.set(edge.source, new Set())
      }
      map.get(edge.source)!.add(edge.target)

      // 反向依赖：target 被 source 依赖
      if (!reverseDependencyMap.has(edge.target)) {
        reverseDependencyMap.set(edge.target, new Set())
      }
      reverseDependencyMap.get(edge.target)!.add(edge.source)
    })

    return { dependencies: map, reverseDependencies: reverseDependencyMap }
  }, [rawEdges])

  // 过滤函数：根据搜索查询返回过滤后的节点和高亮节点
  const handleFilter = useMemo(
    () => (nodes: GraphNodeData[], query: string) => {
      if (!query.trim()) {
        return {
          filteredNodeIds: new Set(nodes.map((n) => n.id)),
          highlightedNodeIds: new Set<string>(),
        }
      }

      const lowerQuery = query.toLowerCase()
      const matchedNodes = nodes.filter(
        (node) =>
          node.fileName.toLowerCase().includes(lowerQuery) ||
          node.path.toLowerCase().includes(lowerQuery) ||
          node.summary?.toLowerCase().includes(lowerQuery)
      )

      // 包含匹配的节点及其依赖和被依赖的节点
      const resultSet = new Set<string>()
      matchedNodes.forEach((node) => {
        resultSet.add(node.id)

        // 添加该节点依赖的节点
        const deps = dependencyMap.dependencies.get(node.id)
        if (deps) {
          deps.forEach((depId) => resultSet.add(depId))
        }

        // 添加依赖该节点的节点
        const reverseDeps = dependencyMap.reverseDependencies.get(node.id)
        if (reverseDeps) {
          reverseDeps.forEach((depId) => resultSet.add(depId))
        }
      })

      return {
        filteredNodeIds: resultSet,
        highlightedNodeIds: new Set(matchedNodes.map((n) => n.id)),
      }
    },
    [dependencyMap]
  )

  // 节点转换函数
  const transformNode = (
    node: GraphNodeData,
    options: { isHighlighted: boolean; isDimmed: boolean }
  ): Node => ({
    id: node.id,
    type: 'custom',
    data: {
      ...node,
      isHighlighted: options.isHighlighted,
      isDimmed: options.isDimmed,
    },
    position: { x: 0, y: 0 }, // 将由布局算法设置
  })

  // MiniMap 节点颜色函数
  const getNodeColor = (node: Node) => {
    const data = node.data as unknown as GraphNodeData & { isHighlighted?: boolean; isDeleted?: boolean }
    if (data.isDeleted) return '#fca5a5'
    if (data.isHighlighted) return '#60a5fa'
    return '#cbd5e1'
  }

  // 统计信息渲染
  const renderStats = (filteredCount: number, totalCount: number, matchedCount: number) => (
    <div className="mt-2 text-xs text-muted-foreground">
      显示 {filteredCount} / {totalCount} 个文件
      {matchedCount > 0 && ` (${matchedCount} 个匹配)`}
    </div>
  )

  return (
    <AdaptiveGraph
      nodes={rawNodes}
      edges={rawEdges}
      nodeTypes={nodeTypes}
      onFilter={handleFilter}
      transformNode={transformNode}
      getNodeColor={getNodeColor}
      onNodeClick={onNodeClick}
      searchPlaceholder="搜索文件名、路径或摘要..."
      renderStats={renderStats}
      className="h-[800px] max-h-[calc(100vh-12rem)]"
      reactFlowProps={{
        nodesDraggable: true,
        nodesConnectable: false,
        elementsSelectable: true,
      }}
    />
  )
}