/**
 * 流程进度布局工具
 *
 * 根据流程定义的 modelJson（nodes + edges）重建真实拓扑，将流程组织为若干"行"（FlowRow）：
 *   - start / end：起点/终点标记
 *   - node / cc：主流程上的单个节点（线性主线）
 *   - branch：条件分支区（在该处列出全部可能的分支路线，并标记实际选择的分支）
 *
 * 状态语义：
 *   - completed：节点已有处理任务或审批记录（历史已处理）
 *   - current：节点处于进行中（有待处理任务，或为实例当前节点）
 *   - passed：节点位于当前节点之前且无任务/记录（导入数据直接跳到中间时，前面的流程视为已走过）
 *   - pending：节点尚未到达 / 未被选择的分支
 *   - neutral：起点/终点/条件节点等非审批节点
 */

export interface FlowLayoutNode {
  id: string
  name: string
  type: string // start / approval / cc / condition / end
  status: 'completed' | 'current' | 'passed' | 'pending' | 'neutral'
  isMyTurn: boolean
  /** 审批节点的完整进度数据（tasks / subNodes 等） */
  nodeProgress?: any
  /** 该节点下的审批记录 */
  records: any[]
}

export interface FlowBranch {
  label: string
  condition: string
  isDefault: boolean
  /** 该分支是否被实际选择（分支内存在已处理任务/记录，或当前节点位于该分支） */
  isChosen: boolean
  nodes: FlowLayoutNode[]
}

export interface FlowRow {
  kind: 'start' | 'node' | 'cc' | 'branch' | 'end'
  /** 单节点行的节点列表（通常 1 个）；分支行无此字段 */
  nodes?: FlowLayoutNode[]
  /** 分支区标题（条件节点名称） */
  title?: string
  branches?: FlowBranch[]
}

const MAX_DEPTH = 300

/**
 * 根据流程模型与进度数据构建布局行
 * @param modelNodes 模型节点 [{id,type,name,properties}]
 * @param modelEdges 模型连线 [{sourceNodeId,targetNodeId,condition:{condition,isDefault,branchName}}]
 * @param progress   进度节点列表（仅审批节点，NodeProgress[]）
 * @param records    审批记录列表（ApprovalRecord[]）
 * @param currentNodeId 当前节点 ID（用于判断"导入跳过"的历史节点与已选择分支）
 */
export function buildFlowLayout(
  modelNodes: any[],
  modelEdges: any[],
  progress: any[],
  records: any[],
  currentNodeId?: string | null
): FlowRow[] {
  if (!Array.isArray(modelNodes) || modelNodes.length === 0) return []

  const nodeMap = new Map<string, any>()
  for (const n of modelNodes) {
    if (n && n.id) nodeMap.set(n.id, n)
  }

  const outgoing = new Map<string, any[]>()
  const incomingCount = new Map<string, number>()
  for (const e of modelEdges || []) {
    if (!e || !e.sourceNodeId || !e.targetNodeId) continue
    if (!nodeMap.has(e.targetNodeId)) continue
    if (!outgoing.has(e.sourceNodeId)) outgoing.set(e.sourceNodeId, [])
    outgoing.get(e.sourceNodeId)!.push(e)
    incomingCount.set(e.targetNodeId, (incomingCount.get(e.targetNodeId) || 0) + 1)
  }

  const progressMap = new Map<string, any>()
  for (const p of progress || []) {
    if (p && p.nodeId) progressMap.set(p.nodeId, p)
  }

  const recordsMap = new Map<string, any[]>()
  for (const r of records || []) {
    if (!r || !r.nodeId) continue
    if (!recordsMap.has(r.nodeId)) recordsMap.set(r.nodeId, [])
    recordsMap.get(r.nodeId)!.push(r)
  }

  // 计算"当前节点的祖先"（从当前节点沿反向边可达的节点）——用于识别导入跳过的主线历史节点
  const ancestors = new Set<string>()
  if (currentNodeId && nodeMap.has(currentNodeId)) {
    const reverse: Map<string, string[]> = new Map()
    for (const e of modelEdges || []) {
      if (!e?.sourceNodeId || !e?.targetNodeId) continue
      if (!nodeMap.has(e.targetNodeId)) continue
      if (!reverse.has(e.targetNodeId)) reverse.set(e.targetNodeId, [])
      reverse.get(e.targetNodeId)!.push(e.sourceNodeId)
    }
    const stack = [currentNodeId]
    while (stack.length) {
      const nid = stack.pop()!
      for (const pre of reverse.get(nid) || []) {
        if (pre && pre !== currentNodeId && !ancestors.has(pre)) {
          ancestors.add(pre)
          stack.push(pre)
        }
      }
    }
  }

  const startNode = modelNodes.find((n) => n.type === 'start')
  const endNodes = modelNodes.filter((n) => n.type === 'end')
  const startId = startNode?.id

  /** 节点是否有实际活动（任务或记录） */
  const isNodeActive = (n: any): boolean => {
    const p = progressMap.get(n.id)
    if (p && p.status && p.status !== 'pending') return true
    if ((recordsMap.get(n.id) || []).length) return true
    return false
  }

  const mkNode = (n: any, status?: FlowLayoutNode['status']): FlowLayoutNode => {
    const p = progressMap.get(n.id)
    return {
      id: n.id,
      name: n.name || n.id,
      type: n.type,
      status: status ?? (n.type === 'start' || n.type === 'end' || n.type === 'condition' ? 'neutral' : 'pending'),
      isMyTurn: !!p?.isMyTurn,
      nodeProgress: p,
      records: recordsMap.get(n.id) || [],
    }
  }

  /** 主线节点状态：优先进度，其次"祖先=已走过"，否则待处理 */
  const mainLineStatus = (n: any): FlowLayoutNode['status'] => {
    const p = progressMap.get(n.id)
    if (p) {
      if (p.status === 'current') return 'current'
      if (p.status === 'completed') return 'completed'
      return 'pending'
    }
    if (n.id === currentNodeId) return 'current'
    if (ancestors.has(n.id)) return 'passed'
    if (n.type === 'cc') return 'completed'
    return 'pending'
  }

  const rows: FlowRow[] = []
  const visited = new Set<string>()

  if (startId && nodeMap.has(startId)) {
    rows.push({ kind: 'start', nodes: [mkNode(nodeMap.get(startId))] })
    visited.add(startId)
  }

  let curId: string | undefined = startId
  let guard = 0
  while (curId && nodeMap.has(curId) && guard++ < MAX_DEPTH) {
    const cur = nodeMap.get(curId)
    const outs = (outgoing.get(curId) || []).filter((e) => e.targetNodeId && nodeMap.has(e.targetNodeId))

    if (cur.type === 'end' || outs.length === 0) {
      if (cur.type === 'end') rows.push({ kind: 'end', nodes: [mkNode(cur)] })
      else rows.push({ kind: 'node', nodes: [mkNode(cur, mainLineStatus(cur))] })
      break
    }

    // 多出边 → 分支节点
    if (outs.length > 1) {
      // 第一遍：收集每条分支的节点链（原始模型节点，不含汇聚点/终点）
      const rawChains: { edge: any; nodes: any[]; merge: string | null }[] = []
      let mergeId: string | null = null
      for (const e of outs) {
        const chainNodes: any[] = []
        let bCurId = e.targetNodeId
        let bGuard = 0
        let branchMerge: string | null = null
        while (bCurId && nodeMap.has(bCurId) && bGuard++ < MAX_DEPTH) {
          const bn = nodeMap.get(bCurId)
          const bin = incomingCount.get(bCurId) || 0
          if (bn.type === 'end' || bin > 1) {
            branchMerge = bCurId
            break
          }
          chainNodes.push(bn)
          const bNext = (outgoing.get(bCurId) || []).filter((be) => be.targetNodeId && nodeMap.has(be.targetNodeId))
          const nextIn = bNext.length === 1 ? incomingCount.get(bNext[0].targetNodeId) || 0 : 0
          if (bNext.length !== 1 || nextIn > 1 || bn.type === 'condition') {
            if (bNext.length === 1 && nextIn > 1) branchMerge = bNext[0].targetNodeId
            break
          }
          bCurId = bNext[0].targetNodeId
        }
        rawChains.push({ edge: e, nodes: chainNodes, merge: branchMerge })
        if (branchMerge) {
          if (mergeId === null) mergeId = branchMerge
          else if (mergeId !== branchMerge) mergeId = null
        }
      }

      // 第二遍：判定各分支是否被选择，再解析分支节点状态
      const branches: FlowBranch[] = rawChains.map((rc) => {
        const cond = rc.edge.condition || {}
        const branchName = cond.branchName || ''
        const condition = cond.condition || ''
        const isDefault = !!cond.isDefault
        // 分支被选择：分支内有活动节点（已处理/进行中/有记录），或当前节点就在该分支
        const isChosen = rc.nodes.some((n) => isNodeActive(n) || n.id === currentNodeId)
        const nodes = rc.nodes.map((n) => {
          if (n.id === currentNodeId) return mkNode(n, 'current')
          const p = progressMap.get(n.id)
          if (p) {
            if (p.status === 'current') return mkNode(n, 'current')
            if (p.status === 'completed') return mkNode(n, 'completed')
            return mkNode(n, 'pending')
          }
          // 无任务/记录：所在分支被选择视为已走过（历史），否则为未选择
          return mkNode(n, isChosen ? 'passed' : 'pending')
        })
        return {
          label: branchName || condition || (isDefault ? '默认分支' : '分支'),
          condition,
          isDefault,
          isChosen,
          nodes,
        }
      })

      rows.push({ kind: 'branch', title: cur.name || cur.id, branches })
      // 所有分支汇聚到同一非终点节点则继续主线；否则流程已在分支内结束
      if (mergeId && nodeMap.has(mergeId) && mergeId !== endNodes[0]?.id) {
        curId = mergeId
      } else {
        curId = undefined
      }
      continue
    }

    // 单出边 → 正常推进
    const nextId = outs[0].targetNodeId
    if (cur.type !== 'start') {
      if (cur.type === 'cc') rows.push({ kind: 'cc', nodes: [mkNode(cur, 'completed')] })
      else rows.push({ kind: 'node', nodes: [mkNode(cur, mainLineStatus(cur))] })
    }
    if (visited.has(nextId)) break // 防环
    visited.add(nextId)
    curId = nextId
  }

  // 兜底：主遍历未覆盖到的节点追加到末尾，保证所有节点都可见
  const emittedIds = new Set<string>()
  for (const r of rows) {
    r.nodes?.forEach((n) => emittedIds.add(n.id))
    r.branches?.forEach((b) => b.nodes.forEach((n) => emittedIds.add(n.id)))
  }
  for (const n of modelNodes) {
    if (n.type === 'start' || n.type === 'end' || n.type === 'condition') continue
    if (emittedIds.has(n.id)) continue
    rows.push({ kind: n.type === 'cc' ? 'cc' : 'node', nodes: [mkNode(n, mainLineStatus(n))] })
  }

  // 结束节点兜底：补上所有尚未展示的终点
  for (const en of endNodes) {
    if (en && nodeMap.has(en.id) && !emittedIds.has(en.id)) {
      rows.push({ kind: 'end', nodes: [mkNode(en)] })
    }
  }
  return rows
}
