import { DataSource, DataSourceOptions } from 'typeorm';
import * as path from 'node:path';
import * as fs from 'node:fs';
import { AppConfig, DbDriver } from '../config/configuration';
import { Tenant } from './landlord/entities/tenant.entity';
import { Domain } from './landlord/entities/domain.entity';
import { MasterAdmin } from './landlord/entities/master-admin.entity';

export const LANDLORD_ENTITIES = [Tenant, Domain, MasterAdmin];

export function buildLandlordDataSourceOptions(cfg: AppConfig): DataSourceOptions {
  const driver: DbDriver = cfg.db.driver;
  const common = {
    entities: LANDLORD_ENTITIES,
    synchronize: true,
    logging: false,
  } as const;

  if (driver === 'mysql') {
    return {
      type: 'mysql',
      host: cfg.db.mysql.host,
      port: cfg.db.mysql.port,
      username: cfg.db.mysql.user,
      password: cfg.db.mysql.password,
      database: cfg.db.mysql.landlordDb,
      charset: 'utf8mb4',
      ...common,
    };
  }

  if (driver === 'postgres') {
    return {
      type: 'postgres',
      host:     cfg.db.postgres.host,
      port:     cfg.db.postgres.port,
      username: cfg.db.postgres.user,
      password: cfg.db.postgres.password,
      database: cfg.db.postgres.database,
      schema:   cfg.db.postgres.landlordSchema,
      ...common,
    };
  }

  // Default: SQLite local dev (sql.js — pure JS, no native bindings)
  const dataDir = path.resolve(process.cwd(), cfg.db.sqlite.dataDir);
  if (!fs.existsSync(dataDir)) fs.mkdirSync(dataDir, { recursive: true });
  return {
    type: 'sqljs',
    location: path.join(dataDir, cfg.db.sqlite.landlordFile),
    autoSave: true,
    useLocalForage: false,
    ...common,
  };
}

export async function ensurePostgresSchema(
  cfg: AppConfig,
  schemaName: string,
): Promise<void> {
  if (cfg.db.driver !== 'postgres') return;
  const { Pool } = await import('pg');
  const pool = new Pool({
    host:     cfg.db.postgres.host,
    port:     cfg.db.postgres.port,
    user:     cfg.db.postgres.user,
    password: cfg.db.postgres.password,
    database: cfg.db.postgres.database,
  });
  await pool.query(`CREATE SCHEMA IF NOT EXISTS "${schemaName}"`);
  await pool.end();
}

export async function createLandlordDataSource(cfg: AppConfig): Promise<DataSource> {
  if (cfg.db.driver === 'postgres') {
    await ensurePostgresSchema(cfg, cfg.db.postgres.landlordSchema);
  }
  const ds = new DataSource(buildLandlordDataSourceOptions(cfg));
  await ds.initialize();
  return ds;
}
