import { logger } from "@/core/logger";
import dotenv from "dotenv";
import { Sequelize } from "sequelize";
import { registerModels } from "./register-models";

dotenv.config();

let sequelizeInstance: Sequelize | null = null;

export function getDatabase(): Sequelize {
  if (sequelizeInstance) {
    return sequelizeInstance;
  }

  sequelizeInstance = new Sequelize(
    process.env.DB_NAME as string,
    process.env.DB_USER as string,
    process.env.DB_PASSWORD as string,
    {
      host: process.env.DB_HOST as string,
      dialect: "mysql",
      port: Number.parseInt(process.env.DB_PORT || "3306", 10),
      dialectOptions: {
        multipleStatements: true,
        dateStrings: true,
        typeCast: true,
      },
      pool: {
        max: 10,
        min: 0,
        acquire: 30000,
        idle: 10000,
      },
      logQueryParameters: true,
      logging: process.env.DB_LOGGING === "true" ? logger.debug : false,
      define: {
        charset: "utf8mb4",
        collate: "utf8mb4_unicode_ci",
        underscored: true,
        timestamps: true,
      },
    }
  );

  return sequelizeInstance;
}

export async function tryConnectToDatabase() {
  const database = getDatabase();

  if (!database) {
    const error = new Error("❌ Database not found.");
    logger.error({
      message: error.message,
      label: "tryConnectToDatabase",
    });
    throw error;
  }
  logger.info({ message: `🔸 Connecting to database...`, label: "tryConnectToDatabase" });

  try {
    await database.authenticate();
    await registerModels(database);

    logger.info({
      message: `✔️${"  "}Database connection established successfully.`,
      label: "tryConnectToDatabase",
      meta: {
        host: process.env.DB_HOST,
        port: process.env.DB_PORT,
        database: process.env.DB_NAME,
        user: process.env.DB_USER,
      },
    });
    return database;
  } catch (error) {
    logger.error({
      message: `❌ Unable to connect to the database: ${(error as Error).message}`,
      error,
      label: "tryConnectToDatabase",
    });
    throw error;
  }
}
