const sqlite3 = require('sqlite3').verbose();
const { Pool } = require('pg');
const path = require('path');
require('dotenv').config();

const isPostgres = !!process.env.DATABASE_URL;
let db;

if (isPostgres) {
  console.log('Connecting to PostgreSQL database...');
  const pool = new Pool({
    connectionString: process.env.DATABASE_URL,
    ssl: { rejectUnauthorized: false } // Required for most cloud providers like Supabase/Neon
  });

  // Mock sqlite3 API for pg
  db = {
    serialize: (callback) => callback(),
    run: (sql, params, callback) => {
      const pgSql = sql.replace(/\?/g, (_, i) => `$${i + 1}`);
      pool.query(sql.replace(/\?/g, (match, i, s) => {
        let count = 0;
        return sql.slice(0, match.index).split('?').length;
      }), params, (err, res) => {
        if (callback) callback(err, res);
      });
    },
    // More accurate ? to $n conversion
    execute: (sql, params = []) => {
      let index = 1;
      const pgSql = sql.replace(/\?/g, () => `$${index++}`);
      return pool.query(pgSql, params);
    },
    get: (sql, params, callback) => {
      db.execute(sql, params)
        .then(res => callback(null, res.rows[0]))
        .catch(err => callback(err));
    },
    all: (sql, params, callback) => {
      db.execute(sql, params)
        .then(res => callback(null, res.rows))
        .catch(err => callback(err));
    },
    run: (sql, params, callback) => {
      if (typeof params === 'function') {
        callback = params;
        params = [];
      }
      db.execute(sql, params)
        .then(res => {
          if (callback) callback(null, { lastID: null, changes: res.rowCount });
        })
        .catch(err => {
          if (callback) callback(err);
        });
    },
    prepare: (sql) => {
      return {
        run: (params, callback) => {
          if (!Array.isArray(params)) params = [params];
          db.run(sql, params, callback);
        },
        finalize: () => {}
      };
    }
  };
} else {
  const dbPath = path.resolve(__dirname, '../../data/election.db');
  const sqliteDb = new sqlite3.Database(dbPath, (err) => {
    if (err) console.error('Error opening database', err.message);
    else console.log('Connected to the SQLite database.');
  });
  db = sqliteDb;
}

function initializeTables() {
  const runQuery = (sql) => {
    return new Promise((resolve, reject) => {
      db.run(sql, (err) => {
        if (err) reject(err);
        else resolve();
      });
    });
  };

  const schema = [
    `CREATE TABLE IF NOT EXISTS positions (
      id ${isPostgres ? 'SERIAL' : 'INTEGER'} PRIMARY KEY ${isPostgres ? '' : 'AUTOINCREMENT'},
      title TEXT NOT NULL UNIQUE,
      display_order INTEGER DEFAULT 0
    )`,
    `CREATE TABLE IF NOT EXISTS config (
      id ${isPostgres ? 'SERIAL' : 'INTEGER'} PRIMARY KEY ${isPostgres ? '' : 'AUTOINCREMENT'},
      role TEXT NOT NULL UNIQUE,
      username TEXT NOT NULL,
      password TEXT NOT NULL
    )`,
    `CREATE TABLE IF NOT EXISTS candidates (
      id ${isPostgres ? 'SERIAL' : 'INTEGER'} PRIMARY KEY ${isPostgres ? '' : 'AUTOINCREMENT'},
      name TEXT NOT NULL,
      position_id INTEGER NOT NULL,
      image_url TEXT,
      bio TEXT
    )`,
    `CREATE TABLE IF NOT EXISTS voters (
      admission_number TEXT PRIMARY KEY,
      has_voted INTEGER DEFAULT 0,
      voted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )`,
    `CREATE TABLE IF NOT EXISTS votes (
      id ${isPostgres ? 'SERIAL' : 'INTEGER'} PRIMARY KEY ${isPostgres ? '' : 'AUTOINCREMENT'},
      candidate_id INTEGER
    )`
  ];

  async function runInit() {
    for (const sql of schema) {
      try {
        await runQuery(sql);
      } catch (err) {
        console.error('Error creating table:', err.message);
      }
    }
    console.log('Tables initialized successfully.');
  }

  runInit();
}

initializeTables();

module.exports = db;
