require("dotenv").config({ quiet: true });

const fs = require("fs").promises;
const path = require("path");
const { Pool } = require("pg");

const ROOT_DIR = path.join(__dirname, "..");
const SCHEMA_PATH = path.join(ROOT_DIR, "db", "schema.sql");

const getConfig = () => ({
  host: process.env.DB_HOST,
  port: Number(process.env.DB_PORT || 5432),
  database: process.env.DB_DATABASE,
  user: process.env.DB_USERNAME,
  password: process.env.DB_PASSWORD,
  ssl: process.env.DB_SSL === "1" ? { rejectUnauthorized: false } : false,
});

const validateConfig = (config) => {
  const missing = ["host", "database", "user", "password"].filter((key) => !config[key]);
  if (missing.length) {
    throw new Error(`Missing PostgreSQL envs: ${missing.join(", ")}`);
  }
};

const run = async () => {
  const config = getConfig();
  validateConfig(config);

  const sql = await fs.readFile(SCHEMA_PATH, "utf-8");
  const pool = new Pool(config);
  try {
    await pool.query("SELECT 1");
    await pool.query(sql);
    console.log("Schema applied successfully.");
  } finally {
    await pool.end();
  }
};

run().catch((error) => {
  console.error("Failed to apply schema:", error.message);
  const msg = String(error.message || "");
  if (error.code === "28P01" || /password authentication failed/i.test(msg)) {
    console.error(
      "\n[DB 인증 실패] .env의 DB_USERNAME·DB_PASSWORD가 PostgreSQL에 등록된 사용자·비밀번호와 일치하는지 확인하세요.",
    );
    console.error(
      "  (원격 DB면 관리자에게 계정을 확인하고, 로컬이면 `sudo -u postgres psql`에서 \\password 사용자명 으로 비밀번호를 맞추세요.)",
    );
  } else if (/ECONNREFUSED|ENOTFOUND/i.test(msg) || error.code === "ECONNREFUSED") {
    console.error("\n[DB 연결 불가] DB_HOST·DB_PORT가 맞는지, 방화벽·PostgreSQL listen_addresses를 확인하세요.");
  } else if (error.code === "28000" || /role .* does not exist/i.test(msg)) {
    console.error(
      "\n[DB 사용자 없음] .env의 DB_USERNAME에 해당하는 PostgreSQL 역할(role)이 서버에 없습니다.",
    );
    console.error(
      "  슈퍼유저로 접속해 CREATE ROLE ... LOGIN PASSWORD '...'; 및 GRANT를 실행하거나, db/bootstrap-role.sql.example을 참고하세요.",
    );
  }
  process.exit(1);
});
