import { createNeonHttpClient } from '@platform-modules/db/postgres/neon-http';
import { createNeonServerlessClient } from '@platform-modules/db/postgres/neon-serverless';
import { createD1Client } from '@platform-modules/db/sqlite/d1';
import type { TransactionalDatabase, Dialect } from '@platform-modules/db';
import { auditSchema } from '@platform-modules/audit';
import { commentsSchema } from '@platform-modules/comments';
import { formsSchema } from '@platform-modules/forms/store';
import { notificationsSchema } from '@platform-modules/notifications/inbox';
import { contentSchema } from '@platform-modules/content';
import { i18nContentSchema } from '@platform-modules/i18n-content/schema';
import { mediaSchema } from './media.js';
import { settingsSchema } from './settings.js';

export class MissingDatabaseError extends Error {
  readonly name = 'MissingDatabaseError';

  constructor() {
    super('No database configured: set DB binding (D1) or DATABASE_URL secret (Neon)');
  }
}

const fullSchema = { 
  ...contentSchema, 
  ...settingsSchema, 
  ...auditSchema, 
  ...mediaSchema, 
  ...commentsSchema, 
  ...formsSchema, 
  ...notificationsSchema,
  ...i18nContentSchema,
};

export type DbEnv = {
  DB?: D1Database;
  DATABASE_URL?: string;
};

export type DbResult = {
  db: TransactionalDatabase<typeof fullSchema>;
  dialect: Dialect;
};

/**
 * Get database client. Prefers D1 (SQLite) if available, falls back to Neon (Postgres).
 * D1 = 1-click CF deploy, no external DB.
 * Neon = opt-in for sites needing Postgres features or scale beyond D1's 10GB.
 */
export function getDb(env: DbEnv): DbResult {
  if (env.DB) {
    return {
      db: createD1Client(env.DB, { schema: fullSchema }) as unknown as TransactionalDatabase<typeof fullSchema>,
      dialect: 'sqlite',
    };
  }

  if (env.DATABASE_URL) {
    return {
      db: createNeonHttpClient({
        connectionString: env.DATABASE_URL,
        schema: fullSchema,
      }) as unknown as TransactionalDatabase<typeof fullSchema>,
      dialect: 'postgres',
    };
  }
  
  throw new MissingDatabaseError();
}

/** Alias for backward compat */
export function getFullDb(env: DbEnv): DbResult {
  return getDb(env);
}

/** Transaction-capable client (D1 supports transactions; neon-http doesn't). */
export function getTransactionalDb(env: DbEnv): DbResult {
  if (env.DB) {
    return {
      db: createD1Client(env.DB, { schema: fullSchema }) as unknown as TransactionalDatabase<typeof fullSchema>,
      dialect: 'sqlite',
    };
  }

  if (env.DATABASE_URL) {
    return {
      db: createNeonServerlessClient({
        connectionString: env.DATABASE_URL,
        schema: fullSchema,
      }) as unknown as TransactionalDatabase<typeof fullSchema>,
      dialect: 'postgres',
    };
  }
  
  throw new MissingDatabaseError();
}

/** @deprecated Use getTransactionalDb */
export const getTransactionalFullDb = getTransactionalDb;