import { Sequelize } from "sequelize";
import { logger } from "../lib/logger";
import { ENV } from "./index";

/**
 * Crea la instancia de Sequelize según ENV (DATABASE_URL o parámetros sueltos),
 * autentica la conexión y devuelve la instancia lista para usar.
 */
export async function tryConnectToDatabase(): Promise<Sequelize> {
  const sequelize = buildSequelize();

  try {
    await sequelize.authenticate();
    logger.info("✔️  Database connection established", {
      label: "database",
      // Info no sensible:
      dialect: sequelize.getDialect(),
      host: (sequelize.config.host ?? "url") as string,
      database: (sequelize.config.database ?? "url") as string,
    });
    return sequelize;
  } catch (error: any) {
    logger.error(`❌ Unable to connect to the database: ${error?.message ?? error}`, {
      label: "database",
    });
    // Cerramos por si quedó algo abierto
    try {
      await sequelize.close();
    } catch {
      /* noop */
    }
    throw error;
  }
}

/**
 * Cierra la instancia de Sequelize (para integrar con el shutdown).
 */
export async function closeDatabase(sequelize: Sequelize): Promise<void> {
  try {
    await sequelize.close();
    logger.info("Database connection closed", { label: "database" });
  } catch (error: any) {
    logger.error(`Error while closing database: ${error?.message ?? error}`, {
      label: "database",
    });
  }
}

function buildSequelize(): Sequelize {
  const common = {
    logging: ENV.DB_LOGGING
      ? (msg: any) => logger.debug(String(msg), { label: "sequelize" })
      : false,
    timezone: ENV.APP_TIMEZONE,
    pool: {
      max: 10,
      min: 0,
      idle: 10000,
      acquire: 30000,
    },
    dialectOptions: {
      timezone: ENV.APP_TIMEZONE,
    },
  } as const;

  if (ENV.DATABASE_URL && ENV.DATABASE_URL.trim() !== "") {
    // URL completa (recomendada p.ej. en Postgres/MariaDB)
    return new Sequelize(ENV.DATABASE_URL, common);
  }

  // Parámetros sueltos (asegurar requeridos mínimos)
  if (!ENV.DB_DIALECT) {
    throw new Error("DB_DIALECT is required when DATABASE_URL is not provided");
  }
  if (!ENV.DB_NAME || !ENV.DB_USER) {
    throw new Error("DB_NAME and DB_USER are required when DATABASE_URL is not provided");
  }

  return new Sequelize(ENV.DB_NAME, ENV.DB_USER, ENV.DB_PASSWORD, {
    host: ENV.DB_HOST,
    port: ENV.DB_PORT,
    dialect: ENV.DB_DIALECT,
    ...common,
  });
}
