import { describe, it, expect } from 'vitest'
import { buildFlowLayout } from '@/utils/flowLayout'

const diamond = {
  nodes: [
    { id: 'start', type: 'start' },
    { id: 'A', type: 'approval', name: '审批A' },
    { id: 'cond', type: 'condition', name: '条件' },
    { id: 'B1', type: 'approval', name: '大额审批' },
    { id: 'B2', type: 'approval', name: '默认审批' },
    { id: 'C', type: 'approval', name: '审批C' },
    { id: 'end', type: 'end' },
  ],
  edges: [
    { sourceNodeId: 'start', targetNodeId: 'A' },
    { sourceNodeId: 'A', targetNodeId: 'cond' },
    { sourceNodeId: 'cond', targetNodeId: 'B1', condition: { condition: 'amount>=1000', isDefault: false } },
    { sourceNodeId: 'cond', targetNodeId: 'B2', condition: { condition: '', isDefault: true } },
    { sourceNodeId: 'B1', targetNodeId: 'C' },
    { sourceNodeId: 'B2', targetNodeId: 'C' },
    { sourceNodeId: 'C', targetNodeId: 'end' },
  ],
}

const allIds = (rows: any[]) =>
  rows.flatMap((r) => {
    const main = (r.nodes || []).map((n: any) => n.id)
    const branch = (r.branches || []).flatMap((b: any) => b.nodes.map((n: any) => n.id))
    return main.concat(branch).concat(r.kind === 'branch' ? [`${r.title}`] : [])
  })

describe('buildFlowLayout', () => {
  it('线性流程全部展示且不重复', () => {
    const linear = {
      nodes: [
        { id: 'start', type: 'start' },
        { id: 'A', type: 'approval', name: 'A' },
        { id: 'B', type: 'approval', name: 'B' },
        { id: 'end', type: 'end' },
      ],
      edges: [
        { sourceNodeId: 'start', targetNodeId: 'A' },
        { sourceNodeId: 'A', targetNodeId: 'B' },
        { sourceNodeId: 'B', targetNodeId: 'end' },
      ],
    }
    const rows = buildFlowLayout(linear.nodes, linear.edges, [
      { nodeId: 'A', status: 'completed' },
      { nodeId: 'B', status: 'current' },
    ], [])
    const ids = allIds(rows)
    expect(ids.filter((x) => x === 'A')).toHaveLength(1)
    expect(ids.filter((x) => x === 'B')).toHaveLength(1)
    expect(rows.filter((r) => r.kind === 'branch')).toHaveLength(0)
  })

  it('菱形分支：两条分支都展示，后续节点也展示，无重复', () => {
    const rows = buildFlowLayout(diamond.nodes, diamond.edges, [
      { nodeId: 'A', status: 'completed' },
      { nodeId: 'B1', status: 'completed' },
      { nodeId: 'C', status: 'current' },
    ], [{ nodeId: 'B1' }], 'C')
    const branchRow = rows.find((r) => r.kind === 'branch')
    expect(branchRow).toBeTruthy()
    expect(branchRow.branches).toHaveLength(2)
    expect(branchRow.branches[0].nodes[0].id).toBe('B1')
    expect(branchRow.branches[1].nodes[0].id).toBe('B2')
    // 后续节点 C、end 在主线上
    expect(rows.some((r) => r.kind === 'node' && r.nodes?.[0]?.id === 'C')).toBe(true)
    expect(rows.some((r) => r.kind === 'end')).toBe(true)
    // 无重复
    const ids = allIds(rows)
    for (const id of ['A', 'B1', 'B2', 'C']) {
      expect(ids.filter((x) => x === id)).toHaveLength(1)
    }
    // 已选择分支标记
    expect(branchRow.branches[0].isChosen).toBe(true)
    expect(branchRow.branches[1].isChosen).toBe(false)
  })

  it('直连合并点：默认分支直连下一节点，后续仍展示', () => {
    const direct = {
      nodes: [
        { id: 'start', type: 'start' },
        { id: 'A', type: 'approval', name: 'A' },
        { id: 'cond', type: 'condition', name: '条件' },
        { id: 'B1', type: 'approval', name: '大额' },
        { id: 'C', type: 'approval', name: 'C' },
        { id: 'end', type: 'end' },
      ],
      edges: [
        { sourceNodeId: 'start', targetNodeId: 'A' },
        { sourceNodeId: 'A', targetNodeId: 'cond' },
        { sourceNodeId: 'cond', targetNodeId: 'B1', condition: { condition: 'x', isDefault: false } },
        { sourceNodeId: 'cond', targetNodeId: 'C', condition: { condition: '', isDefault: true } },
        { sourceNodeId: 'B1', targetNodeId: 'C' },
        { sourceNodeId: 'C', targetNodeId: 'end' },
      ],
    }
    const rows = buildFlowLayout(direct.nodes, direct.edges, [
      { nodeId: 'A', status: 'completed' },
      { nodeId: 'C', status: 'current' },
    ], [], 'C')
    const branchRow = rows.find((r) => r.kind === 'branch')
    expect(branchRow).toBeTruthy()
    expect(branchRow.branches).toHaveLength(2)
    // C 在分支后主线上出现一次
    expect(rows.filter((r) => r.nodes?.some((n: any) => n.id === 'C'))).toHaveLength(1)
    expect(rows.some((r) => r.kind === 'end')).toBe(true)
  })

  it('导入型：前面主线节点标记为已走过(passed)', () => {
    const rows = buildFlowLayout(diamond.nodes, diamond.edges, [
      { nodeId: 'C', status: 'current' },
    ], [], 'C')
    const aRow = rows.find((r) => r.nodes?.[0]?.id === 'A')
    expect(aRow?.nodes?.[0]?.status).toBe('passed')
  })

  it('分支内节点状态：未选择分支为 pending', () => {
    const rows = buildFlowLayout(diamond.nodes, diamond.edges, [
      { nodeId: 'A', status: 'completed' },
      { nodeId: 'B1', status: 'completed' },
      { nodeId: 'C', status: 'current' },
    ], [], 'C')
    const branchRow = rows.find((r) => r.kind === 'branch')
    expect(branchRow.branches[0].nodes[0].status).toBe('completed')
    expect(branchRow.branches[1].nodes[0].status).toBe('pending')
  })
})
