/**
 * Dialect-specific operations that diverge across SQLite / PostgreSQL / MySQL.
 * Shared store code uses Drizzle's typed query builder for everything else.
 */

export type DialectKind = "sqlite" | "postgres" | "mysql";

export interface IdempotencyInsertValues {
  keyHash: string;
  claimId: string;
  requestHash: string;
  createdAt: string;
  expiresAt: string;
}

export interface DialectAdapter {
  readonly kind: DialectKind;

  /**
   * Run `work` inside a single database transaction. Nested calls are not supported.
   * SQLite uses BEGIN IMMEDIATE (serialized via an in-process queue);
   * PostgreSQL / MySQL use the driver transaction API with AsyncLocalStorage
   * binding so concurrent requests cannot steal each other's session.
   */
  transaction<T>(work: () => Promise<T>): Promise<T>;

  /**
   * Delete run rows beyond the newest `keepCount`, ordered by (started_at desc, id desc).
   * SQL shape differs per dialect (LIMIT -1 OFFSET vs OFFSET-only vs derived-table NOT IN).
   */
  deleteRetentionTail(keepCount: number): Promise<void>;

  /**
   * Insert an in_progress idempotency row, ignoring primary-key conflicts.
   * Returns true when a new row was inserted (claim acquired).
   * Must participate in the active `transaction()` session when called inside one.
   */
  insertIgnoreIdempotency(values: IdempotencyInsertValues): Promise<boolean>;
}

/**
 * Minimal surface stores need from a dialect: schema tables, drizzle session, and
 * the divergent adapter operations. The drizzle `db` type differs per driver
 * (BetterSQLite3Database vs NodePgDatabase vs MySql2Database), so it is left open.
 *
 * `db` resolves to the current AsyncLocalStorage transaction session when inside
 * `adapter.transaction()`, otherwise the dialect root handle.
 */
export interface RuntimeDialect {
  readonly kind: DialectKind;
  readonly db: RuntimeDrizzleDb;
  readonly schema: RuntimeSchemaTables;
  adapter: DialectAdapter;
  close(): Promise<void>;
}

/**
 * Open shape for the six runtime tables. Each dialect schema exports identically
 * named symbols; stores only rely on column property names (camelCase in JS).
 */
export interface RuntimeSchemaTables {
  connections: unknown;
  oauthClientConfigs: unknown;
  oauthStates: unknown;
  runtimeTokens: unknown;
  runs: unknown;
  idempotencyRecords: unknown;
}

/**
 * Drizzle session used by stores. Intentionally loose so SQLite (sync thenable),
 * node-postgres, and mysql2 sessions share one call site. Callers always `await`.
 */
// oxlint-disable-next-line typescript/no-explicit-any
export type RuntimeDrizzleDb = any;
