import { makeProjectMajorKey } from '@/lib/pricingScaleLink'

export const buildScaleProjectMajorMap = <TRow>(
  rows: TRow[] | undefined,
  resolveProjectIndex: (row: Partial<TRow>) => number,
  resolveMajorDictId: (row: Partial<TRow>) => string | undefined
) => {
  const valueMap = new Map<string, TRow>()
  for (const row of rows || []) {
    const majorDictId = resolveMajorDictId(row)
    if (!majorDictId) continue
    valueMap.set(makeProjectMajorKey(resolveProjectIndex(row), majorDictId), row)
  }
  return valueMap
}

export const getScaleProjectMajorMappedRow = <TRow>(
  valueMap: Map<string, TRow>,
  projectIndex: number,
  majorDictId: string,
  options?: { cloneFromProjectOne?: boolean }
) => (
  valueMap.get(makeProjectMajorKey(projectIndex, majorDictId))
  || (
    options?.cloneFromProjectOne && projectIndex > 1
      ? valueMap.get(makeProjectMajorKey(1, majorDictId))
      : undefined
  )
)

export const mergeScaleRowsFromProjectMajorMap = <TRow, TSource>(options: {
  rowsFromDb: TSource[] | undefined
  projectCount: number
  buildDefaultRows: (projectCount: number) => TRow[]
  resolveProjectIndex: (row: Partial<TRow> | Partial<TSource>) => number
  resolveMajorDictId: (row: Partial<TRow> | Partial<TSource>) => string | undefined
  cloneFromProjectOne?: boolean
  mergeRow: (defaultRow: TRow, fromDb: TSource | undefined) => TRow
}) => {
  const valueMap = buildScaleProjectMajorMap(
    options.rowsFromDb,
    row => options.resolveProjectIndex(row),
    row => options.resolveMajorDictId(row)
  )

  return options.buildDefaultRows(options.projectCount).map(defaultRow => {
    const majorDictId = options.resolveMajorDictId(defaultRow)
    if (!majorDictId) return defaultRow
    const fromDb = getScaleProjectMajorMappedRow(
      valueMap,
      options.resolveProjectIndex(defaultRow),
      majorDictId,
      { cloneFromProjectOne: options.cloneFromProjectOne }
    )
    return options.mergeRow(defaultRow, fromDb)
  })
}
