import { useEffect, useMemo, useState } from "react"
import { Link } from "react-router-dom"
import {
  ArrowRight,
  CheckCircle,
  Server,
  CreditCard,
  FileText,
  Globe,
  Layers2,
  ShieldCheck,
  ShoppingCart,
  User,
  Wallet,
  Zap,
} from "lucide-react"
import {
  Background,
  Controls,
  Handle,
  MarkerType,
  Panel,
  Position,
  ReactFlow,
  type Edge,
  type Node,
  type NodeProps,
  type NodeTypes,
} from "@xyflow/react"
import "@xyflow/react/dist/style.css"
import { Button, Card, Spin } from "antd"
import { useAuth } from "../contexts/AuthContext"
import { listServers, type ServerItem } from "../api/servers"

type ProfileItem = {
  key: "email" | "phone" | "password"
  label: string
  desc: string
  done: boolean
}

const DASHBOARD_STATUS_META: Record<string, { label: string; color: string; bg: string; border: string; text: string }> = {
  active: { label: "运行中", color: "success", bg: "#f6ffed", border: "#b7eb8f", text: "#389e0d" },
  off: { label: "已关机", color: "default", bg: "#f5f5f5", border: "#d9d9d9", text: "#595959" },
  provisioning: { label: "开通中", color: "processing", bg: "#e6f4ff", border: "#91caff", text: "#1677ff" },
  suspended: { label: "已暂停", color: "warning", bg: "#fff7e6", border: "#ffd591", text: "#d46b08" },
}

function getDashboardStatusMeta(status: string, upstreamPower?: string | null) {
  if (status === "active" && upstreamPower) {
    const normalized = upstreamPower.toLowerCase()
    const isOff = normalized === "off" || normalized.includes("off") || upstreamPower.includes("关")
    const isOn = normalized === "on" || upstreamPower.includes("开") || upstreamPower.includes("运行")

    if (isOff) return DASHBOARD_STATUS_META.off
    if (isOn) return DASHBOARD_STATUS_META.active
    return {
      label: upstreamPower,
      color: "processing",
      bg: "#e6f4ff",
      border: "#91caff",
      text: "#1677ff",
    }
  }

  return DASHBOARD_STATUS_META[status] ?? {
    label: status || "未知",
    color: "default",
    bg: "#f5f5f5",
    border: "#d9d9d9",
    text: "#595959",
  }
}

export default function Dashboard() {
  const { user } = useAuth()
  const [loading, setLoading] = useState(true)
  const [servers, setServers] = useState<ServerItem[]>([])

  useEffect(() => {
    let mounted = true
    const load = async () => {
      try {
        const res = await listServers()
        if (mounted) setServers(res.data.data ?? [])
      } finally {
        if (mounted) setLoading(false)
      }
    }
    load()
    return () => {
      mounted = false
    }
  }, [])

  const profileItems: ProfileItem[] = [
    { key: "email", label: "绑定邮箱", desc: "接收账单、通知与安全提醒", done: !!user?.email },
    { key: "phone", label: "绑定手机", desc: "用于验证码登录和身份校验", done: !!user?.phone },
    { key: "password", label: "设置密码", desc: "保留密码登录作为备用方式", done: !!user?.has_password },
  ]

  const pendingCount = profileItems.filter((item) => !item.done).length
  const balance = ((user?.balance || 0) / 100).toFixed(2)
  const displayName = user?.nickname || user?.username || "用户"
  const normalServers = servers.filter((server) => ["active", "provisioning", "suspended"].includes(server.status))
  const activeServers = servers.filter((server) => getDashboardStatusMeta(server.status, server.upstream_power).label === "运行中")
  const expiringSoonCount = normalServers.filter((server) => {
    if (!server.expires_at) return false
    const expiresAt = new Date(server.expires_at).getTime()
    const now = Date.now()
    const sevenDays = 7 * 24 * 60 * 60 * 1000
    return expiresAt >= now && expiresAt <= now + sevenDays
  }).length
  const resourceGraphServers = normalServers

  if (loading) {
    return (
      <div style={{ minHeight: 260, display: "flex", alignItems: "center", justifyContent: "center" }}>
        <Spin size="large" tip="正在加载仪表盘" />
      </div>
    )
  }

  const quickActions = [
    { label: "购买云服务器", desc: "选择区域、配置与计费周期", icon: ShoppingCart, href: "/store" },
    { label: "服务器管理", desc: "查看实例状态和远程控制", icon: Server, href: "/control/server" },
    { label: "财务管理", desc: "充值、账单和交易记录", icon: CreditCard, href: "/finance" },
    { label: "订单管理", desc: "查看购买与续费订单", icon: FileText, href: "/orders" },
  ]

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 24 }}>
      {/* Welcome banner */}
      <Card
        styles={{ body: { padding: 28 } }}
      >
        <div style={{ display: "flex", flexDirection: "column", gap: 16 }} className="welcome-banner">
          <div style={{ flex: 1 }}>
            <span className="inline-block rounded-full border border-sky-100 bg-sky-50 px-2.5 py-0.5 text-[11px] font-medium text-sky-500 mb-3">
              QingYun Cloud Console
            </span>
            <h2 style={{ fontSize: 24, fontWeight: 700, color: "#1f2937", margin: 0 }}>欢迎回来，{displayName}</h2>
            <p style={{ marginTop: 8, maxWidth: 560, fontSize: 14, color: "#9ca3af", marginBottom: 0 }}>
              集中管理云服务器、订单、余额与账户安全。这里会展示资源概览、待处理事项和常用操作入口。
            </p>
          </div>
          <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
            <Link to="/finance">
              <Button icon={<Wallet size={16} />}>充值</Button>
            </Link>
            <Link to="/store">
              <Button type="primary" icon={<ShoppingCart size={16} />}>购买服务</Button>
            </Link>
          </div>
        </div>
      </Card>

      {/* Stats row */}
      <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 16 }}>
        <Card size="small">
          <div style={{ padding: "4px 0" }}>
            <div style={{ fontSize: 12, color: "#9ca3af", marginBottom: 8 }}>账户余额</div>
            <div style={{ display: "flex", alignItems: "baseline", gap: 2 }}>
              <span style={{ fontSize: 12, color: "#9ca3af" }}>¥</span>
              <span style={{ fontSize: 28, fontWeight: 700, color: "#1f2937" }}>{balance}</span>
            </div>
            <div style={{ fontSize: 12, color: "#9ca3af", marginTop: 4 }}>可用于购买、续费和升级服务</div>
          </div>
        </Card>
        <Card size="small">
          <div style={{ padding: "4px 0" }}>
            <div style={{ fontSize: 12, color: "#9ca3af", marginBottom: 8 }}>运行中的云服务器</div>
            <div style={{ display: "flex", alignItems: "baseline", gap: 4 }}>
              <span style={{ fontSize: 28, fontWeight: 700, color: "#1f2937" }}>{activeServers.length}</span>
              <span style={{ fontSize: 14, color: "#9ca3af" }}>台</span>
            </div>
            <div style={{ fontSize: 12, color: "#9ca3af", marginTop: 4 }}>
              {expiringSoonCount > 0 ? `${expiringSoonCount} 台实例即将到期` : "暂无即将到期的实例"}
            </div>
          </div>
        </Card>
        <Card size="small">
          <div style={{ padding: "4px 0" }}>
            <div style={{ fontSize: 12, color: "#9ca3af", marginBottom: 8 }}>账户安全</div>
            <div style={{ fontSize: 28, fontWeight: 700, color: pendingCount === 0 ? "#52c41a" : "#faad14" }}>
              {pendingCount === 0 ? "优秀" : `${pendingCount} 项待完善`}
            </div>
            <div style={{ fontSize: 12, color: "#9ca3af", marginTop: 4 }}>
              {pendingCount === 0 ? "关键安全项已完成" : "建议尽快完善安全设置"}
            </div>
          </div>
        </Card>
      </div>

      {/* Quick actions + Security */}
      <div style={{ display: "grid", gridTemplateColumns: "2fr 1fr", gap: 16 }}>
        <Card
          title={
            <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
              <div className="flex h-9 w-9 items-center justify-center rounded-lg bg-sky-50">
                <Zap size={18} className="text-sky-500" />
              </div>
              <span style={{ fontSize: 15, fontWeight: 600, color: "#1f2937" }}>快捷操作</span>
            </div>
          }
        >
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
            {quickActions.map((item) => (
              <Link
                key={item.label}
                to={item.href}
                className="group block rounded-xl border border-gray-100 bg-gray-50/50 p-4 transition-all duration-200 hover:border-sky-200 hover:bg-sky-50/30 hover:shadow-sm"
                style={{ textDecoration: "none" }}
              >
                <div style={{ display: "flex", alignItems: "flex-start", gap: 12 }}>
                  <div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-white shadow-sm ring-1 ring-gray-100 group-hover:ring-sky-200">
                    <item.icon size={20} className="text-gray-400 group-hover:text-sky-500" />
                  </div>
                  <div>
                    <div style={{ fontSize: 14, fontWeight: 500, color: "#1f2937" }}>{item.label}</div>
                    <div style={{ fontSize: 12, color: "#9ca3af", marginTop: 2 }}>{item.desc}</div>
                  </div>
                </div>
              </Link>
            ))}
          </div>
        </Card>

        <Card
          title={
            <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
              <div className="flex h-9 w-9 items-center justify-center rounded-lg bg-sky-50">
                <ShieldCheck size={18} className="text-sky-500" />
              </div>
              <span style={{ fontSize: 15, fontWeight: 600, color: "#1f2937" }}>安全与资料</span>
            </div>
          }
          extra={<Link to="/settings" style={{ fontSize: 12, color: "#0ea5e9" }}>去设置</Link>}
        >
          <ul style={{ listStyle: "none", margin: 0, padding: 0 }}>
            {profileItems.map((item) => (
              <li
                key={item.key}
                style={{
                  display: "flex",
                  alignItems: "center",
                  gap: 12,
                  padding: "12px 4px",
                  borderBottom: "1px solid #f9fafb",
                }}
              >
                {item.done ? (
                  <CheckCircle size={18} style={{ color: "#2dd4bf", flexShrink: 0 }} strokeWidth={2} />
                ) : (
                  <User size={18} style={{ color: "#d1d5db", flexShrink: 0 }} strokeWidth={2} />
                )}
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                    <span style={{ fontSize: 14, fontWeight: 500, color: "#374151" }}>{item.label}</span>
                    <span
                      className={`shrink-0 rounded-full border px-2 py-0.5 text-[10px] font-medium ${
                        item.done
                          ? "border-teal-100 bg-teal-50 text-teal-500"
                          : "border-amber-100 bg-amber-50 text-amber-500"
                      }`}
                    >
                      {item.done ? "已完成" : "待完善"}
                    </span>
                  </div>
                  <div style={{ fontSize: 12, color: "#9ca3af", marginTop: 2 }}>{item.desc}</div>
                </div>
              </li>
            ))}
          </ul>
        </Card>
      </div>

      {/* Resource graph */}
      <Card
        title={
          <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
            <div className="flex h-9 w-9 items-center justify-center rounded-lg bg-sky-50">
              <Server size={18} className="text-sky-500" />
            </div>
            <span style={{ fontSize: 15, fontWeight: 600, color: "#1f2937" }}>资源概览</span>
          </div>
        }
        extra={
          <Link to="/control/server" style={{ display: "inline-flex", alignItems: "center", gap: 4, fontSize: 12, color: "#0ea5e9" }}>
            查看全部 <ArrowRight size={12} />
          </Link>
        }
      >
        <div style={{ minHeight: 260, display: "flex", alignItems: "center", justifyContent: "center" }}>
          {resourceGraphServers.length > 0 ? (
            <ResourceGraph servers={resourceGraphServers} />
          ) : (
            <div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 12, padding: "32px 0", textAlign: "center" }}>
              <Server size={36} style={{ color: "#d1d5db" }} strokeWidth={1.5} />
              <p style={{ fontSize: 14, fontWeight: 500, color: "#374151", margin: 0 }}>还没有可管理的资源</p>
              <p style={{ maxWidth: 320, fontSize: 12, color: "#9ca3af", margin: 0 }}>
                购买云服务器后，实例状态、到期时间、带宽和远程控制入口会显示在这里。
              </p>
              <Link to="/store">
                <Button type="primary">去购买第一台服务器</Button>
              </Link>
            </div>
          )}
        </div>
      </Card>

      <style>{`
        @media (max-width: 768px) {
          .welcome-banner { flex-direction: column !important; }
          .welcome-banner > div:last-child { flex-direction: column; width: 100%; }
          .welcome-banner > div:last-child a { width: 100%; }
          .welcome-banner > div:last-child a button { width: 100%; }
        }
      `}</style>
    </div>
  )
}

// --- ResourceGraph internals ---

type GroupFlowData = Record<string, unknown> & {
  label: string
  title: string
  subtitle: string
  icon: "product" | "region" | "security"
  color: string
  acceptsInput: boolean
}

type ServerFlowData = Record<string, unknown> & {
  serverId: number
  title: string
  productName: string
  statusLabel: string
  statusColor: string
  accentColor: string
  networkLabel: string
  cpuLabel: string
  memoryLabel: string
  bandwidthLabel: string
  regionLabel: string
  securityLabel: string | null
}

type GroupFlowNode = Node<GroupFlowData, "relation">
type ServerFlowNode = Node<ServerFlowData, "server">
type ResourceFlowNode = GroupFlowNode | ServerFlowNode

const GROUP_NODE_WIDTH = 230
const GROUP_NODE_HEIGHT = 82
const SERVER_NODE_WIDTH = 330
const SERVER_NODE_HEIGHT = 122
const SERVER_ROW_GAP = 148
const PRODUCT_LAYER_X = 24
const REGION_LAYER_X = 340
const SECURITY_LAYER_X = 680
const SERVER_LAYER_X_WITH_SECURITY = 1040
const SERVER_LAYER_X_WITHOUT_SECURITY = 700

const resourceGraphNodeTypes = {
  relation: GroupFlowNodeCard,
  server: ServerFlowNodeCard,
} satisfies NodeTypes

function ResourceGraph({ servers }: { servers: ServerItem[] }) {
  const { nodes, edges, graphHeight, graphWidth } = useMemo(() => {
    const serverTop = (index: number) => 70 + index * SERVER_ROW_GAP
    const hasSecurityGroups = servers.some((server) => Boolean(getSecurityInfo(server)))
    const serverLayerX = hasSecurityGroups ? SERVER_LAYER_X_WITH_SECURITY : SERVER_LAYER_X_WITHOUT_SECURITY

    type RelationGroup = {
      key: string
      label: string
      title: string
      subtitle: string
      icon: GroupFlowData["icon"]
      color: string
      count: number
      acceptsInput: boolean
    }

    const products = new Map<string, RelationGroup>()
    const regions = new Map<string, RelationGroup>()
    const securityGroups = new Map<string, RelationGroup>()
    const centers = new Map<string, { total: number; count: number }>()

    const addCenter = (key: string, value: number) => {
      const current = centers.get(key) ?? { total: 0, count: 0 }
      centers.set(key, { total: current.total + value, count: current.count + 1 })
    }

    servers.forEach((server, index) => {
      const centerY = serverTop(index) + SERVER_NODE_HEIGHT / 2
      const productKey = getProductKey(server)
      const regionInfo = getRegionInfo(server)
      const securityInfo = getSecurityInfo(server)

      if (!products.has(productKey)) {
        products.set(productKey, {
          key: productKey,
          label: "套餐",
          title: productKey,
          subtitle: "套餐规格",
          icon: "product",
          color: "#1677ff",
          count: 0,
          acceptsInput: false,
        })
      }
      products.get(productKey)!.count += 1
      addCenter(productKey, centerY)

      if (!regions.has(regionInfo.key)) {
        regions.set(regionInfo.key, {
          key: regionInfo.key,
          label: "地区/线路",
          title: regionInfo.title,
          subtitle: regionInfo.subtitle,
          icon: "region",
          color: "#13a8a8",
          count: 0,
          acceptsInput: true,
        })
      }
      regions.get(regionInfo.key)!.count += 1
      addCenter(regionInfo.key, centerY)

      if (securityInfo) {
        if (!securityGroups.has(securityInfo.key)) {
          securityGroups.set(securityInfo.key, {
            key: securityInfo.key,
            label: "安全组",
            title: securityInfo.title,
            subtitle: securityInfo.subtitle,
            icon: "security",
            color: "#722ed1",
            count: 0,
            acceptsInput: true,
          })
        }
        securityGroups.get(securityInfo.key)!.count += 1
        addCenter(securityInfo.key, centerY)
      }
    })

    const layoutColumn = (groups: RelationGroup[]) => {
      const ordered = groups
        .map((group, index) => {
          const center = centers.get(group.key)
          return {
            key: group.key,
            desiredY: center ? center.total / center.count - GROUP_NODE_HEIGHT / 2 : 70 + index * 120,
          }
        })
        .sort((a, b) => a.desiredY - b.desiredY)
      const yMap = new Map<string, number>()
      let cursor = 44
      ordered.forEach((item) => {
        const y = Math.max(item.desiredY, cursor)
        yMap.set(item.key, y)
        cursor = y + GROUP_NODE_HEIGHT + 28
      })
      return yMap
    }

    const relationNode = (group: RelationGroup, id: string, x: number, yMap: Map<string, number>): GroupFlowNode => {
      const y = yMap.get(group.key) ?? 70

      return {
        id,
        type: "relation",
        position: { x, y },
        data: {
          label: group.label,
          title: group.title,
          subtitle: `${group.count} 台实例 · ${group.subtitle}`,
          icon: group.icon,
          color: group.color,
          acceptsInput: group.acceptsInput,
        },
        targetPosition: Position.Left,
        sourcePosition: Position.Right,
        style: { width: GROUP_NODE_WIDTH },
      }
    }

    const productList = Array.from(products.values())
    const regionList = Array.from(regions.values())
    const securityList = Array.from(securityGroups.values())
    const productY = layoutColumn(productList)
    const regionY = layoutColumn(regionList)
    const securityY = layoutColumn(securityList)
    const productIds = new Map(productList.map((group, index) => [group.key, `product-${index}`]))
    const regionIds = new Map(regionList.map((group, index) => [group.key, `region-${index}`]))
    const securityIds = new Map(securityList.map((group, index) => [group.key, `security-${index}`]))

    const productNodes = productList.map((group) => (
      relationNode(group, productIds.get(group.key)!, PRODUCT_LAYER_X, productY)
    ))
    const regionNodes = regionList.map((group) => (
      relationNode(group, regionIds.get(group.key)!, REGION_LAYER_X, regionY)
    ))
    const securityNodes = securityList.map((group) => (
      relationNode(group, securityIds.get(group.key)!, SECURITY_LAYER_X, securityY)
    ))

    const serverNodes: ServerFlowNode[] = servers.map((server, index) => {
      const statusMeta = getDashboardStatusMeta(server.status, server.upstream_power)
      const regionInfo = getRegionInfo(server)
      const securityInfo = getSecurityInfo(server)

      return {
        id: `server-${server.id}`,
        type: "server",
        position: { x: serverLayerX, y: serverTop(index) },
        data: {
          serverId: server.id,
          title: server.hostname || `实例 #${server.id}`,
          productName: server.product_name || server.product_group_name || "云服务器",
          statusLabel: statusMeta.label,
          statusColor: statusMeta.color,
          accentColor: statusMeta.text,
          networkLabel: server.main_ip || "-",
          cpuLabel: formatCpu(server.cpu),
          memoryLabel: formatMemory(server.memory),
          bandwidthLabel: formatBandwidth(server.in_bw, server.out_bw),
          regionLabel: regionInfo.title,
          securityLabel: securityInfo?.title ?? null,
        },
        targetPosition: Position.Left,
        style: { width: SERVER_NODE_WIDTH },
      }
    })

    const flowEdges: Edge[] = []
    const edgeSeen = new Set<string>()
    const addEdge = (
      source: string,
      target: string,
      color: string,
      animated = false,
    ) => {
      const id = `${source}-${target}`
      if (edgeSeen.has(id)) return
      edgeSeen.add(id)
      flowEdges.push({
        id,
        source,
        target,
        type: "smoothstep",
        animated,
        markerEnd: {
          type: MarkerType.ArrowClosed,
          color,
          width: 16,
          height: 16,
        },
        style: {
          stroke: color,
          strokeWidth: 1.5,
        },
      })
    }

    servers.forEach((server) => {
      const productId = productIds.get(getProductKey(server))
      const regionInfo = getRegionInfo(server)
      const regionId = regionIds.get(regionInfo.key)
      const securityInfo = getSecurityInfo(server)
      const serverId = `server-${server.id}`
      const isLive = server.status === "active" || server.status === "provisioning"

      if (productId && regionId) addEdge(productId, regionId, "#91caff")
      if (securityInfo) {
        const securityId = securityIds.get(securityInfo.key)
        if (regionId && securityId) addEdge(regionId, securityId, "#5cdbd3")
        if (securityId) addEdge(securityId, serverId, "#b37feb", isLive)
      } else if (regionId) {
        addEdge(regionId, serverId, "#91caff", isLive)
      }
    })

    const maxRelationBottom = Math.max(
      0,
      ...[productY, regionY, securityY].flatMap((map) => (
        Array.from(map.values()).map((y) => y + GROUP_NODE_HEIGHT)
      )),
    )
    const contentHeight = Math.max(
      380,
      servers.length > 0 ? serverTop(servers.length - 1) + SERVER_NODE_HEIGHT + 70 : 340,
      maxRelationBottom + 70,
    )
    const contentWidth = (hasSecurityGroups ? SERVER_LAYER_X_WITH_SECURITY : SERVER_LAYER_X_WITHOUT_SECURITY)
      + SERVER_NODE_WIDTH
      + 80

    return {
      nodes: [...productNodes, ...regionNodes, ...securityNodes, ...serverNodes] as ResourceFlowNode[],
      edges: flowEdges,
      graphHeight: Math.min(720, contentHeight),
      graphWidth: contentWidth,
    }
  }, [servers])

  return (
    <div className="w-full overflow-x-auto pb-0.5">
      <div
        style={{
          minWidth: graphWidth,
          height: graphHeight,
          minHeight: 380,
        }}
        className="rounded-lg border border-gray-100 bg-white overflow-hidden text-left"
      >
        <ReactFlow<ResourceFlowNode, Edge>
          nodes={nodes}
          edges={edges}
          nodeTypes={resourceGraphNodeTypes}
          fitView
          fitViewOptions={{ padding: 0.12, maxZoom: 1, duration: 360 }}
          minZoom={0.7}
          maxZoom={1.2}
          nodesDraggable={false}
          nodesConnectable={false}
          elementsSelectable={false}
          zoomOnDoubleClick={false}
          panOnScroll
          proOptions={{ hideAttribution: true }}
        >
          <Background color="#eef2f7" gap={18} />
          <Controls showInteractive={false} position="bottom-right" />
          <Panel position="top-left">
            <div className="flex flex-wrap gap-1.5">
              <span className="rounded-md border border-blue-100 bg-blue-50 px-2 py-0.5 text-[11px] font-medium text-blue-500">套餐</span>
              <span className="rounded-md border border-teal-100 bg-teal-50 px-2 py-0.5 text-[11px] font-medium text-teal-500">地区/线路</span>
              <span className="rounded-md border border-purple-100 bg-purple-50 px-2 py-0.5 text-[11px] font-medium text-purple-500">安全组</span>
              <span className="rounded-md border border-gray-100 bg-gray-50 px-2 py-0.5 text-[11px] font-medium text-gray-500">实例配置</span>
            </div>
          </Panel>
        </ReactFlow>
      </div>
    </div>
  )
}

function GroupFlowNodeCard({ data }: NodeProps<GroupFlowNode>) {
  const iconEl = data.icon === "product" ? <Layers2 size={16} />
    : data.icon === "security" ? <ShieldCheck size={16} />
    : <Globe size={16} />

  const tagColor = data.icon === "product"
    ? "border-blue-100 bg-blue-50 text-blue-500"
    : data.icon === "security"
    ? "border-purple-100 bg-purple-50 text-purple-500"
    : "border-teal-100 bg-teal-50 text-teal-500"

  return (
    <div className="w-[230px] min-h-[82px] rounded-lg border border-gray-200 bg-white p-3 shadow-[0_8px_22px_rgba(15,23,42,0.06)]">
      {data.acceptsInput && (
        <Handle type="target" position={Position.Left} style={{ background: data.color, borderColor: data.color }} />
      )}
      <Handle type="source" position={Position.Right} style={{ background: data.color, borderColor: data.color }} />
      <div style={{ display: "flex", alignItems: "flex-start", gap: 10 }}>
        <span className="flex h-[34px] w-[34px] shrink-0 items-center justify-center rounded-lg bg-gray-50" style={{ color: data.color }}>
          {iconEl}
        </span>
        <div style={{ flex: 1, minWidth: 0 }}>
          <span className={`inline-block rounded-md border px-1.5 py-0.5 text-[10px] font-medium mb-1 ${tagColor}`}>{data.label}</span>
          <p className="text-sm font-medium text-gray-800 truncate" style={{ margin: 0 }}>{data.title}</p>
          <p className="text-xs text-gray-400 truncate" style={{ margin: 0 }}>{data.subtitle}</p>
        </div>
      </div>
    </div>
  )
}

function ServerFlowNodeCard({ data }: NodeProps<ServerFlowNode>) {
  return (
    <div className="w-[330px] min-h-[122px] rounded-lg border border-gray-200 bg-white p-3 shadow-[0_8px_22px_rgba(15,23,42,0.06)]">
      <Handle type="target" position={Position.Left} style={{ background: data.accentColor, borderColor: data.accentColor }} />
      <Link to={`/control/server/${data.serverId}`} className="nodrag nopan block text-inherit no-underline" style={{ textDecoration: "none", color: "inherit" }}>
        <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
          <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
            <div style={{ display: "flex", alignItems: "center", gap: 8, minWidth: 0 }}>
              <Server size={16} style={{ color: data.accentColor, flexShrink: 0 }} />
              <p className="text-sm font-medium text-gray-800 truncate max-w-[190px]" style={{ margin: 0 }}>{data.title}</p>
            </div>
            <span className="shrink-0 rounded-md border border-gray-100 bg-gray-50 px-1.5 py-0.5 text-[10px] font-medium text-gray-600">{data.statusLabel}</span>
          </div>
          <p className="text-xs text-gray-400" style={{ margin: 0 }}>#{data.serverId} · {data.productName}</p>
          <div style={{ display: "flex", flexWrap: "wrap", gap: 4 }}>
            <span className="rounded-md border border-gray-100 bg-gray-50 px-1.5 py-0.5 text-[10px] text-gray-600">CPU {data.cpuLabel}</span>
            <span className="rounded-md border border-gray-100 bg-gray-50 px-1.5 py-0.5 text-[10px] text-gray-600">内存 {data.memoryLabel}</span>
            <span className="rounded-md border border-gray-100 bg-gray-50 px-1.5 py-0.5 text-[10px] text-gray-600">带宽 {data.bandwidthLabel}</span>
          </div>
          <div style={{ display: "flex", flexWrap: "wrap", gap: 4 }}>
            <span className="rounded-md border border-teal-100 bg-teal-50 px-1.5 py-0.5 text-[10px] text-teal-500">{data.regionLabel}</span>
            {data.securityLabel && (
              <span className="rounded-md border border-purple-100 bg-purple-50 px-1.5 py-0.5 text-[10px] text-purple-500">{data.securityLabel}</span>
            )}
          </div>
          <div style={{ display: "flex", alignItems: "center", gap: 6, fontSize: 12, color: "#9ca3af" }}>
            <Globe size={12} />{data.networkLabel}
          </div>
        </div>
      </Link>
    </div>
  )
}

function getProductKey(server: ServerItem) {
  return server.product_name || "云服务器"
}

function getRegionInfo(server: ServerItem) {
  const title = server.product_group_name || "默认地区/线路"
  const area = server.product_group_area
  const node = server.product_group_node
  const networkType = server.product_group_network_type?.trim()
  const key = area != null
    ? `area:${area}`
    : node != null
      ? `node:${node}`
      : `group:${title}`
  const details = [
    networkType,
    area != null ? `区域 ${area}` : null,
    node != null ? `节点 ${node}` : null,
  ].filter(Boolean)

  return {
    key,
    title,
    subtitle: details.length > 0 ? details.join(" · ") : "地区/线路",
  }
}

function getSecurityInfo(server: ServerItem) {
  const id = server.security_group_id == null ? "" : String(server.security_group_id).trim()
  const name = server.security_group_name?.trim() || ""
  if (!id && !name) return null
  if (id === "0") return null

  return {
    key: id ? `security:${id}` : `security-name:${name}`,
    title: name || `安全组 ${id}`,
    subtitle: id ? `ID ${id}` : "安全组",
  }
}

function formatCpu(cpu: number | null) {
  return cpu == null ? "-" : `${cpu} 核`
}

function formatMemory(memoryMb: number | null) {
  if (memoryMb == null) return "-"
  if (memoryMb >= 1024) {
    const gb = memoryMb / 1024
    return `${Number.isInteger(gb) ? gb : gb.toFixed(1)} GB`
  }
  return `${memoryMb} MB`
}

function formatBandwidth(inBw: number | null, outBw: number | null) {
  if (inBw == null && outBw == null) return "-"
  return `${inBw ?? "-"} / ${outBw ?? "-"} Mbps`
}
