/**
 * 现货盘口档位合并与切片（与 Flutter aggregateSpotDepthLevels + _SpotOrderBookPanel 一致）
 */

export interface SpotBookRow {
  price: string
  amount: string
  total: string
}

/** 按 depthPrecision 分桶合并数量，保持首次出现价位顺序 */
export function aggregateSpotDepthLevels(
  levels: [number, number][],
  depthPrecision: number,
): [number, number][] {
  const merged = new Map<number, number>()
  const keysInOrder: number[] = []
  for (const [p, q] of levels) {
    if (p <= 0 || q <= 0 || !Number.isFinite(p) || !Number.isFinite(q)) continue
    const key = Number(p.toFixed(depthPrecision))
    if (!merged.has(key)) keysInOrder.push(key)
    merged.set(key, (merged.get(key) ?? 0) + q)
  }
  return keysInOrder.map(k => [k, merged.get(k)!])
}

function cumTotals(rows: [number, number][], priceDp: number): SpotBookRow[] {
  let acc = 0
  const dp = Math.min(18, Math.max(0, Math.floor(priceDp)))
  return rows.map(([p, q]) => {
    acc += q
    return {
      price: p.toFixed(dp),
      amount: String(q),
      total: String(acc),
    }
  })
}

/**
 * @param bookMode 0 双向 | 1 仅卖 | 2 仅买（与 App _bookMode 一致）
 * @param n 单侧展示档位数（full 模式一般为 10）
 */
export function buildSpotOrderBookDisplay(
  rawAsks: [number, number][],
  rawBids: [number, number][],
  depthPrecision: number,
  bookMode: 0 | 1 | 2,
  n: number,
): { askRows: SpotBookRow[]; bidRows: SpotBookRow[] } {
  // 卖盘按用户规则：先从最小价开始取值，再按价高→价低展示
  const aggregatedAsksAsc = aggregateSpotDepthLevels(rawAsks, depthPrecision)
  aggregatedAsksAsc.sort((a, b) => a[0] - b[0])

  const aggregatedBids = aggregateSpotDepthLevels(rawBids, depthPrecision)
  aggregatedBids.sort((a, b) => b[0] - a[0])

  // 精度切换后可能出现“最高买价 == 最低卖价”的重叠档位，直接移除一条避免盘口重合
  if (aggregatedAsksAsc.length > 0 && aggregatedBids.length > 0) {
    while (aggregatedAsksAsc.length > 0
      && aggregatedBids.length > 0
      && aggregatedAsksAsc[0][0] === aggregatedBids[0][0]) {
      // 优先移除一档卖盘（也可理解为把最优卖价上抬一档）
      aggregatedAsksAsc.shift()
    }
  }

  // 单边盘口应是双向盘口的同一连续区间“多展示几条”，而不是翻倍扩大取值范围
  const askTake = bookMode === 2 ? 0 : n
  const bidTake = bookMode === 1 ? 0 : n

  // 卖盘：先按升序取前 askTake（最小价起），再按降序展示
  const askSliceAsc =
    askTake > 0 && aggregatedAsksAsc.length > 0
      ? aggregatedAsksAsc.slice(0, Math.min(askTake, aggregatedAsksAsc.length))
      : []
  const askRowsRaw = [...askSliceAsc].sort((a, b) => b[0] - a[0])

  // 买盘：首条即最优买 → 取前 bidTake 档，首行紧贴中间价
  const bidSlice = bidTake > 0 ? aggregatedBids.slice(0, bidTake) : []

  const askRows = cumTotals(askRowsRaw, depthPrecision)
  const bidRows = cumTotals(bidSlice, depthPrecision)

  return { askRows, bidRows }
}

export function spotPrecisionLabel(precision: number): string {
  if (precision <= 0) return '1'
  return `0.${'0'.repeat(precision - 1)}1`
}
