import { getMajorIdAliasMap } from '@/sql'

const majorIdAliasMap = getMajorIdAliasMap()

type ScaleLinkRow = {
  id?: unknown
  projectIndex?: unknown
  majorDictId?: unknown
  path?: unknown
}

type ScaleValueLinkRow = ScaleLinkRow & {
  amount?: unknown
  landArea?: unknown
  isGroupRow?: unknown
}

const normalizeProjectCount = (value: unknown) => {
  const parsed = Number(value)
  if (!Number.isFinite(parsed)) return 1
  return Math.max(1, Math.floor(parsed))
}

export const parseProjectIndexFromPathKey = (value: string) => {
  const match = /^project-(\d+)$/.exec(value)
  if (!match) return null
  return normalizeProjectCount(Number(match[1]))
}

export const parseScopedRowId = (id: unknown) => {
  const rawId = String(id || '')
  const match = /^(\d+)::(.+)$/.exec(rawId)
  if (!match) {
    return {
      projectIndex: 1,
      majorDictId: rawId
    }
  }
  return {
    projectIndex: normalizeProjectCount(Number(match[1])),
    majorDictId: String(match[2] || '').trim()
  }
}

export const resolveScaleRowProjectIndex = (row: ScaleLinkRow | undefined) => {
  if (!row) return 1
  if (typeof row.projectIndex === 'number' && Number.isFinite(row.projectIndex)) {
    return normalizeProjectCount(row.projectIndex)
  }
  if (Array.isArray(row.path) && row.path.length > 0) {
    const projectIndexFromPath = parseProjectIndexFromPathKey(String(row.path[0] || ''))
    if (projectIndexFromPath != null) return projectIndexFromPath
  }
  return parseScopedRowId(row.id).projectIndex
}

export const resolveScaleRowMajorDictId = (row: ScaleLinkRow | undefined) => {
  if (!row) return ''
  const direct = String(row.majorDictId || '').trim()
  if (direct) return majorIdAliasMap.get(direct) || direct
  const parsed = parseScopedRowId(row.id).majorDictId
  return majorIdAliasMap.get(parsed) || parsed
}

export const makeProjectMajorKey = (projectIndex: number, majorDictId: string) =>
  `${normalizeProjectCount(projectIndex)}:${String(majorDictId || '').trim()}`

export const buildContractScaleMap = <TRow extends ScaleLinkRow>(rows: TRow[] | undefined) => {
  const map = new Map<string, TRow>()
  for (const row of rows || []) {
    const majorDictId = resolveScaleRowMajorDictId(row)
    if (!majorDictId) continue
    const projectIndex = resolveScaleRowProjectIndex(row)
    map.set(makeProjectMajorKey(projectIndex, majorDictId), row)
  }
  return map
}

export const buildContractScaleIdMap = <TRow extends ScaleLinkRow>(rows: TRow[] | undefined) => {
  const map = new Map<string, TRow>()
  for (const row of rows || []) {
    const rowId = String(row?.id || '').trim()
    if (!rowId) continue
    map.set(rowId, row)
    const aliasId = majorIdAliasMap.get(rowId)
    if (aliasId && !map.has(aliasId)) {
      map.set(aliasId, row)
    }
  }
  return map
}

export const buildContractScaleProjectTotals = <TRow extends ScaleValueLinkRow>(
  rows: TRow[] | undefined,
  totalAmount?: unknown
) => {
  const map = new Map<number, { amount: number | null; landArea: number | null }>()

  const normalizedTotalAmount =
    typeof totalAmount === 'number' && Number.isFinite(totalAmount)
      ? totalAmount
      : null

  if (normalizedTotalAmount != null) {
    map.set(1, {
      amount: normalizedTotalAmount,
      landArea: null
    })
  }

  for (const row of rows || []) {
    if (row?.isGroupRow !== true) continue
    const projectIndex = resolveScaleRowProjectIndex(row)
    const current = map.get(projectIndex) || { amount: null, landArea: null }
    const nextAmount =
      current.amount != null
        ? current.amount
        : (typeof row?.amount === 'number' && Number.isFinite(row.amount) ? row.amount : null)
    const nextLandArea =
      current.landArea != null
        ? current.landArea
        : (typeof row?.landArea === 'number' && Number.isFinite(row.landArea) ? row.landArea : null)
    map.set(projectIndex, {
      amount: nextAmount,
      landArea: nextLandArea
    })
  }

  return map
}

export const getContractScaleProjectTotalsByRow = (
  row: ScaleLinkRow | undefined,
  totalsMap: Map<number, { amount: number | null; landArea: number | null }>
) => {
  const projectIndex = resolveScaleRowProjectIndex(row)
  return totalsMap.get(projectIndex)
    || (projectIndex > 1 ? totalsMap.get(1) : undefined)
    || { amount: null, landArea: null }
}

export const getContractScaleRowByMajor = <TRow extends ScaleLinkRow>(
  row: ScaleLinkRow,
  map: Map<string, TRow>,
  idMap?: Map<string, TRow>
) => {
  const directRowId = String(row.id || '').trim()
  if (directRowId && idMap?.has(directRowId)) return idMap.get(directRowId)
  const parsedMajorId = parseScopedRowId(row.id).majorDictId
  if (parsedMajorId && idMap?.has(parsedMajorId)) return idMap.get(parsedMajorId)
  const majorDictId = resolveScaleRowMajorDictId(row)
  if (!majorDictId) return undefined
  const projectIndex = resolveScaleRowProjectIndex(row)
  return map.get(makeProjectMajorKey(projectIndex, majorDictId))
    || (projectIndex > 1 ? map.get(makeProjectMajorKey(1, majorDictId)) : undefined)
}

export const normalizeChangedScaleRowIds = (rowIds?: Array<string | number>) =>
  new Set(
    (rowIds || [])
      .map(id => {
        const rawId = String(id || '').trim()
        if (!rawId) return rawId
        const parsedMajorId = parseScopedRowId(rawId).majorDictId
        return majorIdAliasMap.get(parsedMajorId) || parsedMajorId
      })
      .filter(Boolean)
  )
