import fs from 'node:fs'
import path from 'node:path'

type NormalizeJsonValue<T> = (value: unknown) => T

export function readJsonFile<T>(
  filePath: string,
  fallback: T | (() => T),
  normalize: NormalizeJsonValue<T>,
): T {
  if (!fs.existsSync(filePath)) {
    return resolveFallback(fallback)
  }

  try {
    const rawText = fs.readFileSync(filePath, 'utf8')
    return normalize(JSON.parse(rawText))
  } catch {
    return resolveFallback(fallback)
  }
}

export function writeJsonFile<T>(
  filePath: string,
  value: unknown,
  normalize: NormalizeJsonValue<T>,
): T {
  const normalized = normalize(value)
  fs.mkdirSync(path.dirname(filePath), { recursive: true })
  fs.writeFileSync(filePath, `${JSON.stringify(normalized, null, 2)}\n`, 'utf8')
  return normalized
}

function resolveFallback<T>(fallback: T | (() => T)): T {
  return typeof fallback === 'function' ? (fallback as () => T)() : fallback
}
