/**
 * Build a `SecretBackendDriver` from a `SecretBackend` row.
 *
 * Lives separate from the service because it's the only place aware of every
 * driver type — adding a new backend means adding one case here and one
 * driver file. Everything else (service, routes, CLI) is type-agnostic.
 */
import type { SecretBackend } from '@prisma/client';
import type { SecretBackendDriver, SecretRefResolver } from './types.js';
import { PlaintextDriver, type PlaintextDriverDeps } from './plaintext.js';
import { OpenBaoDriver, type OpenBaoConfig } from './openbao.js';

export interface DriverFactoryDeps {
  plaintext: PlaintextDriverDeps;
  /** Resolves `{secretName, key}` against the plaintext backend — used by remote drivers' auth. */
  secretRefResolver: SecretRefResolver;
  /** Overridable for tests. */
  fetch?: typeof globalThis.fetch;
}

export function createDriver(row: SecretBackend, deps: DriverFactoryDeps): SecretBackendDriver {
  switch (row.type) {
    case 'plaintext':
      return new PlaintextDriver(deps.plaintext);

    case 'openbao': {
      const cfg = row.config as unknown as OpenBaoConfig;
      if (!cfg.url) {
        throw new Error(`SecretBackend '${row.name}' (openbao): config.url is required`);
      }
      const auth = cfg.auth ?? 'token';
      if (auth === 'token') {
        const t = cfg as Extract<OpenBaoConfig, { auth?: 'token' }>;
        if (!t.tokenSecretRef?.name || !t.tokenSecretRef?.key) {
          throw new Error(
            `SecretBackend '${row.name}' (openbao token auth): config.tokenSecretRef {name, key} is required`,
          );
        }
      } else if (auth === 'kubernetes') {
        const k = cfg as Extract<OpenBaoConfig, { auth: 'kubernetes' }>;
        if (!k.role) {
          throw new Error(
            `SecretBackend '${row.name}' (openbao kubernetes auth): config.role is required`,
          );
        }
      } else {
        throw new Error(`SecretBackend '${row.name}' (openbao): unknown auth '${String(auth)}'`);
      }
      const driverDeps: { fetch?: typeof globalThis.fetch; secretRefResolver: SecretRefResolver } = {
        secretRefResolver: deps.secretRefResolver,
      };
      if (deps.fetch !== undefined) driverDeps.fetch = deps.fetch;
      return new OpenBaoDriver(cfg, driverDeps);
    }

    default:
      throw new Error(`Unknown SecretBackend type: ${row.type}`);
  }
}
