import 'dotenv/config';
import 'reflect-metadata';
import mysql, { RowDataPacket } from 'mysql2/promise';
import { env } from '../main/config/env';
import { AppDataSource, initializeDatabase, runMigrations } from '../infrastructure/persistence/data-source';
import { redisClient } from '../infrastructure/cache/redis-client';

const mysqlConnectionOptions = {
  host: env.DB_HOST,
  port: env.DB_PORT,
  user: env.DB_USER,
  password: env.DB_PASS,
};

const createDatabaseIfNotExists = async (): Promise<void> => {
  const connection = await mysql.createConnection(mysqlConnectionOptions);
  try {
    await connection.query(
      'CREATE DATABASE IF NOT EXISTS ?? CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci',
      [env.DB_NAME],
    );
  } finally {
    await connection.end();
  }
};

const databaseHasTables = async (): Promise<boolean> => {
  const connection = await mysql.createConnection({
    ...mysqlConnectionOptions,
    database: env.DB_NAME,
  });
  try {
    const [rows] = await connection.query<RowDataPacket[]>(
      'SELECT COUNT(*) as count FROM information_schema.tables WHERE table_schema = ?',
      [env.DB_NAME],
    );
    return Number(rows[0]?.count ?? 0) > 0;
  } finally {
    await connection.end();
  }
};

const run = async (): Promise<void> => {
  await createDatabaseIfNotExists();

  const hasTables = await databaseHasTables();
  if (hasTables) {
    // eslint-disable-next-line no-console
    console.info('Database already exists and has tables; skipping schema build.');
  } else {
    await initializeDatabase();
    if (!AppDataSource.options.synchronize) {
      await runMigrations();
    }
  }

  await redisClient.quit();
  process.exit(0);
};

run().catch((error) => {
  // eslint-disable-next-line no-console
  console.error('Database setup failed', error);
  process.exit(1);
});
