/**
 * useElkLayout — elkjs compound graph 自動排版
 * ==============================================
 * Sprint 5R B2: 取代硬編碼 position，改用 elkjs 自動計算
 *
 * 支援:
 *   - Compound graph (GroupNode → ServiceNode 父子關係)
 *   - 依賴邊線參與排版
 *   - 展開/收合狀態
 *   - 節點尺寸估算
 *
 * 建立時間: 2026-04-10 (台北時區)
 * 建立者: Claude Code (Sprint 5R B2)
 */

import { useState, useEffect } from 'react'
import ELK from 'elkjs/lib/elk.bundled.js'
import type { Node, Edge } from '@xyflow/react'

// =============================================================================
// Constants
// =============================================================================

const elk = new ELK()

/** 群組節點尺寸 (收合時) */
const GROUP_COLLAPSED = { width: 220, height: 90 }
/** 服務節點尺寸 */
const SERVICE_NODE = { width: 130, height: 44 }
/** 群組展開時 padding */
const GROUP_PADDING = 20

// =============================================================================
// ELK options
// =============================================================================

const ELK_OPTIONS = {
  'elk.algorithm': 'layered',
  'elk.direction': 'DOWN',
  'elk.layered.spacing.nodeNodeBetweenLayers': '60',
  'elk.spacing.nodeNode': '30',
  'elk.padding': '[top=50,left=20,bottom=20,right=20]',
  'elk.layered.nodePlacement.strategy': 'BRANDES_KOEPF',
}

// =============================================================================
// Types
// =============================================================================

export interface ElkLayoutResult {
  nodes: Node[]
  loading: boolean
}

// =============================================================================
// Hook
// =============================================================================

/**
 * 將 React Flow 節點/邊線丟進 elkjs，取得帶有正確 position 的節點陣列
 *
 * @param rawNodes  來自 useTopologyData 的原始節點
 * @param edges     來自 useTopologyData 的邊線 (有助於 elk 排版)
 * @param expandedGroups  Set<string> — 已展開的群組 ID
 */
export function useElkLayout(
  rawNodes: Node[],
  edges: Edge[],
  expandedGroups: Set<string>,
): ElkLayoutResult {
  const [nodes, setNodes] = useState<Node[]>(rawNodes)
  const [loading, setLoading] = useState(false)

  useEffect(() => {
    if (rawNodes.length === 0) {
      setNodes([])
      return
    }

    setLoading(true)

    // 分類節點
    const groupNodes = rawNodes.filter(n => n.type === 'groupNode')
    const serviceNodes = rawNodes.filter(n => n.type === 'serviceNode')

    // 建立 ELK Graph
    const elkGraph = {
      id: 'root',
      layoutOptions: ELK_OPTIONS,
      children: groupNodes.map(group => {
        const isExpanded = expandedGroups.has(group.id)
        const children = serviceNodes.filter(n => n.parentId === group.id)

        if (!isExpanded || children.length === 0) {
          // 收合: 群組作為單一葉節點
          return {
            id: group.id,
            width: GROUP_COLLAPSED.width,
            height: GROUP_COLLAPSED.height,
          }
        }

        // 展開: 群組作為 compound node，子節點自動排列
        const svcsPerRow = Math.ceil(Math.sqrt(children.length))
        const cols = Math.min(svcsPerRow, 3)
        const rows = Math.ceil(children.length / cols)
        const expandedWidth = cols * (SERVICE_NODE.width + GROUP_PADDING) + GROUP_PADDING * 2
        const expandedHeight = rows * (SERVICE_NODE.height + GROUP_PADDING) + GROUP_PADDING * 3 + 40 // 40 for header

        return {
          id: group.id,
          width: expandedWidth,
          height: expandedHeight,
          layoutOptions: {
            'elk.algorithm': 'layered',
            'elk.direction': 'RIGHT',
            'elk.spacing.nodeNode': '10',
            'elk.padding': '[top=40,left=10,bottom=10,right=10]',
          },
          children: children.map((svc, i) => ({
            id: svc.id,
            width: SERVICE_NODE.width,
            height: SERVICE_NODE.height,
            // 預設位置，elk 會覆蓋
            x: (i % cols) * (SERVICE_NODE.width + GROUP_PADDING) + GROUP_PADDING,
            y: Math.floor(i / cols) * (SERVICE_NODE.height + GROUP_PADDING) + 40,
          })),
        }
      }),
      // 只加入跨群組的邊線 (elk 排版用)
      edges: edges
        .filter(e => {
          const srcNode = rawNodes.find(n => n.id === e.source)
          const tgtNode = rawNodes.find(n => n.id === e.target)
          return srcNode?.parentId !== tgtNode?.parentId
        })
        .map(e => ({
          id: e.id,
          sources: [e.source],
          targets: [e.target],
        })),
    }

    elk.layout(elkGraph).then(result => {
      if (!result.children) {
        setLoading(false)
        return
      }

      // 將 elk 計算的位置映射回 React Flow 節點
      const positioned = new Map<string, { x: number; y: number }>()

      result.children.forEach(elkNode => {
        positioned.set(elkNode.id, { x: elkNode.x ?? 0, y: elkNode.y ?? 0 })
        // 子節點 (展開時)
        if (elkNode.children) {
          elkNode.children.forEach(child => {
            positioned.set(child.id, { x: child.x ?? 0, y: child.y ?? 0 })
          })
        }
      })

      const updatedNodes = rawNodes.map(node => {
        const pos = positioned.get(node.id)
        if (!pos) return node
        return { ...node, position: pos }
      })

      setNodes(updatedNodes)
      setLoading(false)
    }).catch(() => {
      // elk 失敗 → 保留原始位置
      setNodes(rawNodes)
      setLoading(false)
    })
  }, [rawNodes, edges, expandedGroups])

  return { nodes, loading }
}
