import type { SQLiteBunDatabase } from "drizzle-orm/bun-sqlite"
import type { NodeSQLiteDatabase } from "drizzle-orm/node-sqlite"
import * as Log from "@saeeol/core/util/log"
import { Filesystem } from "@/util/filesystem"
import { Glob } from "@saeeol/core/util/glob"

const log = Log.create({ service: "json-migration" })

export type Progress = {
  current: number
  total: number
  label: string
}

export type Options = {
  progress?: (event: Progress) => void
}

export type Stats = {
  projects: number
  sessions: number
  messages: number
  parts: number
  todos: number
  permissions: number
  shares: number
  errors: string[]
}

export type Orphans = {
  sessions: number
  todos: number
  permissions: number
  shares: number
}

export function createStats(): Stats {
  return { projects: 0, sessions: 0, messages: 0, parts: 0, todos: 0, permissions: 0, shares: 0, errors: [] }
}

export async function listFiles(pattern: string, cwd: string) {
  return Glob.scan(pattern, { cwd, absolute: true })
}

export async function readBatch(files: string[], start: number, end: number, errs: string[]) {
  const count = end - start
  const tasks = new Array(count)
  for (let i = 0; i < count; i++) tasks[i] = Filesystem.readJson(files[start + i])
  const results = await Promise.allSettled(tasks)
  const items = new Array(count)
  for (let i = 0; i < results.length; i++) {
    const result = results[i]
    if (result.status === "fulfilled") { items[i] = result.value; continue }
    errs.push(`failed to read ${files[start + i]}: ${result.reason}`)
  }
  return items
}

export function insertBatch(
  db: SQLiteBunDatabase<any, any> | NodeSQLiteDatabase<any, any>,
  values: unknown[],
  table: Parameters<typeof db.insert>[0],
  label: string,
  errs: string[],
) {
  if (values.length === 0) return 0
  try {
    db.insert(table).values(values).onConflictDoNothing().run()
    return values.length
  } catch (e) {
    errs.push(`failed to migrate ${label} batch: ${e}`)
    return 0
  }
}

export { log }
