"use client"

import { useState, useMemo, useCallback } from "react"
import {
  ReactFlow,
  Background,
  BackgroundVariant,
  Controls,
  MiniMap,
  ReactFlowProvider,
  useReactFlow,
  type Node,
  type Edge,
} from "@xyflow/react"
import "@xyflow/react/dist/style.css"
import { useTranslations } from "next-intl"
import { toast } from "sonner"
import { Share2 } from "lucide-react"
import { usePermission } from "@/shared/hooks/use-permission"
import { Permissions } from "@/shared/types/permissions"
import { EmptyState } from "@/shared/components/ui/empty-state"
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/shared/components/ui/select"
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/shared/components/ui/dialog"
import { Button } from "@/shared/components/ui/button"
import type { GraphLayoutMode, GraphViewMode, GraphNodeData } from "../types"
import { computeGraphLayout } from "../graph-layout"
import type { GraphLayoutNodeData } from "../graph-layout"
import { useGraphData } from "../hooks/use-graph-data"
import {
  createPrerequisiteAction,
  deletePrerequisiteAction,
} from "../actions"
import { GraphKpNode } from "./graph-kp-node"
import { GraphPrerequisiteEdge } from "./graph-prerequisite-edge"
import { GraphToolbar } from "./graph-toolbar"
import { GraphNodeDetailPanel } from "./graph-node-detail-panel"
import { ForceKnowledgeGraph } from "./force-graph"

const nodeTypes = { kpNode: GraphKpNode }
const edgeTypes = { prerequisiteEdge: GraphPrerequisiteEdge }

/** 章节颜色调色板 */
const CHAPTER_COLORS = [
  "#3b82f6", "#ef4444", "#10b981", "#f59e0b",
  "#8b5cf6", "#ec4899", "#06b6d4", "#84cc16",
]

interface KnowledgeGraphProps {
  textbookId: string
  /** 初始视图模式，默认 structure */
  initialViewMode?: GraphViewMode
  /** 初始布局模式，默认 hierarchical（分层有向图） */
  initialLayoutMode?: GraphLayoutMode
}

function KnowledgeGraphInner({ textbookId, initialViewMode = "structure", initialLayoutMode = "hierarchical" }: KnowledgeGraphProps) {
  const t = useTranslations("textbooks")
  const { hasPermission } = usePermission()
  const canEdit = hasPermission(Permissions.TEXTBOOK_UPDATE)
  const reactFlow = useReactFlow()

  const [viewMode, setViewMode] = useState<GraphViewMode>(initialViewMode)
  const [layoutMode, setLayoutMode] = useState<GraphLayoutMode>(initialLayoutMode)
  const [searchText, setSearchText] = useState("")
  const [selectedKpId, setSelectedKpId] = useState<string | null>(null)
  // 添加前置依赖对话框状态
  const [addPrereqOpen, setAddPrereqOpen] = useState(false)
  const [newPrereqId, setNewPrereqId] = useState<string>("")
  const [isSavingPrereq, setIsSavingPrereq] = useState(false)

  const { data, isLoading, isRefreshing, error, reload } = useGraphData(textbookId, viewMode)

  // 教师可查看班级掌握度，学生可查看个人掌握度
  const availableViewModes: GraphViewMode[] = canEdit
    ? ["structure", "class-mastery"]
    : ["structure", "student-mastery"]

  // 章节颜色映射
  const chapterColorMap = useMemo(() => {
    const map = new Map<string, string>()
    if (!data) return map
    const chapterIds = [...new Set(
      data.knowledgePoints
        .map((kp) => kp.chapterId)
        .filter((id): id is string => id !== null),
    )]
    chapterIds.forEach((id, index) => {
      map.set(id, CHAPTER_COLORS[index % CHAPTER_COLORS.length]!)
    })
    return map
  }, [data])

  const layout = useMemo(() => {
    if (!data) return { nodes: [], edges: [], width: 0, height: 0 }
    return computeGraphLayout(data.knowledgePoints)
  }, [data])

  // 搜索高亮
  const matchedIds = useMemo(() => {
    if (!searchText || !data) return new Set<string>()
    const searchLower = searchText.toLowerCase()
    return new Set(
      data.knowledgePoints
        .filter((kp) => kp.name.toLowerCase().includes(searchLower))
        .map((kp) => kp.id),
    )
  }, [searchText, data])

  // 关联节点高亮（选中节点的前置+后置）
  const relatedIds = useMemo(() => {
    if (!selectedKpId || !data) return new Set<string>()
    const related = new Set<string>([selectedKpId])
    const selectedKp = data.knowledgePoints.find((kp) => kp.id === selectedKpId)
    if (selectedKp) {
      for (const id of selectedKp.prerequisiteIds) related.add(id)
      for (const kp of data.knowledgePoints) {
        if (kp.prerequisiteIds.includes(selectedKpId)) related.add(kp.id)
      }
    }
    return related
  }, [selectedKpId, data])

  // 从已加载数据计算前置/后置列表（避免 server-only 导入）
  const prerequisites = useMemo<{ id: string; name: string; description: string | null }[]>(() => {
    if (!selectedKpId || !data) return []
    const selectedKp = data.knowledgePoints.find((kp) => kp.id === selectedKpId)
    if (!selectedKp) return []
    return data.knowledgePoints
      .filter((kp) => selectedKp.prerequisiteIds.includes(kp.id))
      .map((kp) => ({ id: kp.id, name: kp.name, description: kp.description }))
  }, [selectedKpId, data])

  const successors = useMemo<{ id: string; name: string; description: string | null }[]>(() => {
    if (!selectedKpId || !data) return []
    return data.knowledgePoints
      .filter((kp) => kp.prerequisiteIds.includes(selectedKpId))
      .map((kp) => ({ id: kp.id, name: kp.name, description: kp.description }))
  }, [selectedKpId, data])

  // 组装 React Flow nodes
  const rfNodes: Node[] = useMemo(() => {
    return layout.nodes.map((node) => {
      const kp = node.data.kp
      const mastery = data?.masteryMap[kp.id] ?? null
      const isSelected = selectedKpId === node.id
      const isHighlighted = !searchText
        ? (selectedKpId === null || relatedIds.has(node.id))
        : matchedIds.has(node.id)

      const graphData: GraphNodeData = {
        kp,
        mastery,
        viewMode,
        isSelected,
        isHighlighted,
        chapterColor: chapterColorMap.get(kp.chapterId ?? "") ?? "#6b7280",
      }

      return {
        ...node,
        data: { ...node.data, graphData },
        selected: isSelected,
      }
    })
  }, [layout, data, selectedKpId, relatedIds, matchedIds, searchText, viewMode, chapterColorMap])

  // 组装 React Flow edges
  const rfEdges: Edge[] = useMemo(() => {
    return layout.edges.map((edge) => ({
      ...edge,
      data: {
        ...edge.data,
        isHighlighted: selectedKpId === null || relatedIds.has(edge.source) || relatedIds.has(edge.target),
      },
    }))
  }, [layout, selectedKpId, relatedIds])

  const onNodeClick = useCallback((_event: unknown, node: Node) => {
    setSelectedKpId(node.id)
  }, [])

  const resetView = useCallback(() => {
    if (layoutMode === "hierarchical") {
      reactFlow.fitView({ duration: 300 })
    }
    setSearchText("")
    setSelectedKpId(null)
  }, [reactFlow, layoutMode])

  const onJumpToKp = useCallback((kpId: string) => {
    setSelectedKpId(kpId)
    if (layoutMode === "hierarchical") {
      reactFlow.fitView({ nodes: [{ id: kpId }], duration: 300 })
    }
  }, [reactFlow, layoutMode])

  // 添加前置依赖
  const handleAddPrerequisite = useCallback(async () => {
    if (!selectedKpId || !newPrereqId || !textbookId) return
    setIsSavingPrereq(true)
    try {
      const formData = new FormData()
      formData.set("knowledgePointId", selectedKpId)
      formData.set("prerequisiteKpId", newPrereqId)
      formData.set("textbookId", textbookId)
      const result = await createPrerequisiteAction(formData)
      if (result.success) {
        toast.success(t("graph.detail.prerequisiteAdded"))
        setAddPrereqOpen(false)
        setNewPrereqId("")
        reload()
      } else {
        toast.error(result.message)
      }
    } catch (e) {
      toast.error(e instanceof Error ? e.message : t("graph.detail.prerequisiteAddFailed"))
    } finally {
      setIsSavingPrereq(false)
    }
  }, [selectedKpId, newPrereqId, textbookId, t, reload])

  // 删除前置依赖
  const handleRemovePrerequisite = useCallback(async (prereqId: string) => {
    if (!selectedKpId || !textbookId) return
    try {
      const formData = new FormData()
      formData.set("knowledgePointId", selectedKpId)
      formData.set("prerequisiteKpId", prereqId)
      formData.set("textbookId", textbookId)
      const result = await deletePrerequisiteAction(formData)
      if (result.success) {
        toast.success(t("graph.detail.prerequisiteRemoved"))
        reload()
      } else {
        toast.error(result.message)
      }
    } catch (e) {
      toast.error(e instanceof Error ? e.message : t("graph.detail.prerequisiteRemoveFailed"))
    }
  }, [selectedKpId, textbookId, t, reload])

  // 可选的前置知识点（排除自身和已是前置的）
  const availablePrereqs = useMemo(() => {
    if (!data || !selectedKpId) return []
    const existing = new Set(data.knowledgePoints.find((kp) => kp.id === selectedKpId)?.prerequisiteIds ?? [])
    return data.knowledgePoints.filter((kp) =>
      kp.id !== selectedKpId && !existing.has(kp.id),
    )
  }, [data, selectedKpId])

  if (isLoading && !data) {
    return (
      <div className="h-full flex items-center justify-center text-sm text-muted-foreground">
        {t("reader.loadingKnowledge")}
      </div>
    )
  }

  if (error) {
    return (
      <EmptyState
        icon={Share2}
        title={t("graph.error.loadFailed")}
        description={error}
        className="h-full border-none shadow-none bg-transparent"
      />
    )
  }

  if (!data || data.knowledgePoints.length === 0) {
    return (
      <EmptyState
        icon={Share2}
        title={t("reader.emptyKnowledge")}
        description={t("reader.emptyKnowledgeDesc")}
        className="h-full border-none shadow-none bg-transparent"
      />
    )
  }

  const selectedKp = selectedKpId ? data.knowledgePoints.find((kp) => kp.id === selectedKpId) : null
  const selectedMastery = selectedKpId ? data.masteryMap[selectedKpId] ?? null : null

  return (
    <div className="flex h-full">
      <div className="flex-1 flex flex-col min-h-0">
        <GraphToolbar
          viewMode={viewMode}
          onViewModeChange={setViewMode}
          availableViewModes={availableViewModes}
          layoutMode={layoutMode}
          onLayoutModeChange={setLayoutMode}
          searchText={searchText}
          onSearchChange={setSearchText}
          onResetView={resetView}
          isRefreshing={isRefreshing}
        />
        <div className="flex-1 min-h-0 relative">
          {layoutMode === "hierarchical" ? (
            <ReactFlow
              nodes={rfNodes}
              edges={rfEdges}
              nodeTypes={nodeTypes}
              edgeTypes={edgeTypes}
              onNodeClick={onNodeClick}
              fitView
              fitViewOptions={{ padding: 0.2 }}
              minZoom={0.2}
              maxZoom={2}
              proOptions={{ hideAttribution: true }}
            >
              <Background variant={BackgroundVariant.Dots} gap={16} size={1} />
              <Controls className="!bg-background !border !rounded-lg" />
              <MiniMap
                className="!bg-background !border !rounded-lg"
                nodeColor={(node) => {
                  // 安全的类型收窄：node.data 是 Record<string, unknown>，
                  // GraphLayoutNodeData 有索引签名 [key: string]: unknown，是 Record 的子类型
                  const data = node.data as GraphLayoutNodeData
                  return data.graphData?.chapterColor ?? "#6b7280"
                }}
              />
            </ReactFlow>
          ) : (
            <ForceKnowledgeGraph
              data={data}
              viewMode={viewMode}
              searchText={searchText}
              selectedKpId={selectedKpId}
              onSelectKp={setSelectedKpId}
            />
          )}
        </div>
      </div>

      {selectedKp && (
        // 任意值 w-[300px]：详情面板固定宽度，保证内容可读性
        <div className="w-[300px] shrink-0">
          <GraphNodeDetailPanel
            kp={selectedKp}
            mastery={selectedMastery}
            prerequisites={prerequisites}
            successors={successors}
            canEdit={canEdit}
            onClose={() => setSelectedKpId(null)}
            onJumpToKp={onJumpToKp}
            onAddPrerequisite={() => setAddPrereqOpen(true)}
            onRemovePrerequisite={handleRemovePrerequisite}
          />
        </div>
      )}

      {/* 添加前置依赖对话框 */}
      <Dialog open={addPrereqOpen} onOpenChange={setAddPrereqOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>{t("graph.detail.addPrerequisiteTitle")}</DialogTitle>
            <DialogDescription>{t("graph.detail.addPrerequisiteDesc")}</DialogDescription>
          </DialogHeader>
          <Select value={newPrereqId} onValueChange={setNewPrereqId}>
            <SelectTrigger>
              <SelectValue placeholder={t("graph.detail.selectPrerequisite")} />
            </SelectTrigger>
            <SelectContent>
              {availablePrereqs.map((kp) => (
                <SelectItem key={kp.id} value={kp.id}>
                  {kp.name}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
          <DialogFooter>
            <Button variant="outline" onClick={() => setAddPrereqOpen(false)}>
              {t("graph.detail.cancel")}
            </Button>
            <Button
              onClick={handleAddPrerequisite}
              disabled={!newPrereqId || isSavingPrereq}
            >
              {isSavingPrereq ? t("graph.detail.saving") : t("graph.detail.confirm")}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  )
}

export function KnowledgeGraph(props: KnowledgeGraphProps) {
  return (
    <ReactFlowProvider>
      <KnowledgeGraphInner {...props} />
    </ReactFlowProvider>
  )
}
