'use strict';

const DIALECT_TO_PACKAGE = {
  postgres: 'pg',
  mysql: 'mysql2/promise',
  oracle: 'oracledb',
  sqlite: 'better-sqlite3'
};

// Lazy module-level cache. Same pattern as lib/utils/database-introspector.js
// which is proven to work inside Bun's compiled binary: a literal `require()`
// call inside a function lets Bun statically detect the dependency and bundle
// it, while keeping module load cheap when a dialect is not used.
let pg, mysql2, oracledb, betterSqlite3;

function getInstallPackageName(packageName) {
  return packageName.split('/')[0];
}

function loadDriver(dialect, options) {
  const opts = options || {};
  const requireFn = opts._requireFn;

  const packageName = DIALECT_TO_PACKAGE[dialect];
  if (!packageName) {
    throw new Error(
      `Unknown dialect: '${dialect}'. Supported: postgres, mysql, oracle, sqlite`
    );
  }

  // Test seam: bypass bundled drivers to allow mock injection in unit tests.
  if (requireFn) {
    try {
      return requireFn(packageName);
    } catch (err) {
      if (err && err.code === 'MODULE_NOT_FOUND') {
        throwDriverNotFound(getInstallPackageName(packageName), dialect);
      }
      throw err;
    }
  }

  switch (dialect) {
    case 'postgres':
      if (!pg) {
        try { pg = require('pg'); }
        catch (err) { throwDriverNotFound('pg', dialect); }
      }
      return pg;
    case 'mysql':
      if (!mysql2) {
        try { mysql2 = require('mysql2/promise'); }
        catch (err) { throwDriverNotFound('mysql2', dialect); }
      }
      return mysql2;
    case 'oracle':
      if (!oracledb) {
        try { oracledb = require('oracledb'); }
        catch (err) { throwDriverNotFound('oracledb', dialect); }
      }
      return oracledb;
    case 'sqlite':
      if (!betterSqlite3) {
        try { betterSqlite3 = require('better-sqlite3'); }
        catch (err) { throwDriverNotFound('better-sqlite3', dialect); }
      }
      return betterSqlite3;
  }
}

function throwDriverNotFound(installName, dialect) {
  const error = new Error(
    `Database driver '${installName}' not found.\n` +
      `Install with: npm install ${installName}`
  );
  error.code = 'DRIVER_NOT_FOUND';
  error.dialect = dialect;
  error.packageName = installName;
  throw error;
}

module.exports = { loadDriver, DIALECT_TO_PACKAGE };
