// Project-ID allocation logic.
//
// Two distinct operations, separated so an abandoned "Neues Projekt" form
// never burns a sequence number:
//   - preview  → read the counter, DO NOT consume (form open / reload / cancel)
//   - allocate → atomically consume the next id (successful save only)
//
// The actual increment lives in the next_project_id() SQL function
// (INSERT .. ON CONFLICT (year) DO UPDATE SET last_number = last_number + 1
// RETURNING), which is race-safe across concurrent callers — two parallel
// saves get two distinct, consecutive ids without an application-level lock.
//
// The route handler at app/api/projects/next-id/route.ts is a thin wrapper
// around these; the testable logic lives here per the repo convention.
import type { SupabaseClient } from '@supabase/supabase-js'

// Mirrors the format of the next_project_id() SQL function: `YYYY_NNN`.
export function formatProjectCode(year: number, num: number): string {
  return `${year}_${String(num).padStart(3, '0')}`
}

export type ProjectCodeResult =
  | { ok: true; projectCode: string }
  | { ok: false; error: unknown }

// Preview mode: read project_id_sequence WITHOUT consuming an id. The value is
// non-binding — the real id is allocated on save via allocateNextProjectCode.
// A missing row for the current year means nothing has been allocated yet → 0.
export async function previewNextProjectCode(
  admin: SupabaseClient,
  year: number,
): Promise<ProjectCodeResult> {
  const { data, error } = await admin
    .from('project_id_sequence')
    .select('last_number')
    .eq('year', year)
    .maybeSingle()
  if (error) return { ok: false, error }
  const lastNumber = (data?.last_number as number | undefined) ?? 0
  return { ok: true, projectCode: formatProjectCode(year, lastNumber + 1) }
}

// Allocation mode: atomically consume the next id. Delegates to next_project_id()
// so the increment is a single race-safe DB round-trip. Call on save only.
export async function allocateNextProjectCode(
  admin: SupabaseClient,
): Promise<ProjectCodeResult> {
  const { data, error } = await admin.rpc('next_project_id')
  if (error) return { ok: false, error }
  return { ok: true, projectCode: data as string }
}
