import initSqlJs from 'sql.js';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import fs from 'fs';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const DB_PATH = join(__dirname, '../data/messages.db');

let db = null;

export async function initDatabase() {
  const SQL = await initSqlJs();

  // Load existing database or create new one
  let dbBuffer;
  if (fs.existsSync(DB_PATH)) {
    dbBuffer = fs.readFileSync(DB_PATH);
    db = new SQL.Database(dbBuffer);
  } else {
    db = new SQL.Database();
  }

  // Create tables
  db.run(`
    CREATE TABLE IF NOT EXISTS messages (
      id TEXT PRIMARY KEY,
      channel_id TEXT NOT NULL,
      author_id TEXT NOT NULL,
      author_name TEXT NOT NULL,
      content TEXT NOT NULL,
      created_at INTEGER NOT NULL,
      fetched_at INTEGER NOT NULL
    )
  `);

  db.run(`CREATE INDEX IF NOT EXISTS idx_channel ON messages(channel_id)`);
  db.run(`CREATE INDEX IF NOT EXISTS idx_created_at ON messages(created_at)`);
  db.run(`CREATE INDEX IF NOT EXISTS idx_fetched_at ON messages(fetched_at)`);

  saveDatabase();
}

function saveDatabase() {
  const data = db.export();
  const buffer = Buffer.from(data);
  fs.writeFileSync(DB_PATH, buffer);
}

export function saveMessage(message) {
  db.run(
    `INSERT OR REPLACE INTO messages (id, channel_id, author_id, author_name, content, created_at, fetched_at)
     VALUES (?, ?, ?, ?, ?, ?, ?)`,
    [
      message.id,
      message.channelId,
      message.authorId,
      message.authorName,
      message.content,
      message.createdAt,
      Date.now(),
    ]
  );
  saveDatabase();
}

export function saveMessages(messages) {
  db.run('BEGIN TRANSACTION');

  const stmt = db.prepare(
    `INSERT OR REPLACE INTO messages (id, channel_id, author_id, author_name, content, created_at, fetched_at)
     VALUES (?, ?, ?, ?, ?, ?, ?)`
  );

  for (const msg of messages) {
    stmt.run([
      msg.id,
      msg.channelId,
      msg.authorId,
      msg.authorName,
      msg.content,
      msg.createdAt,
      Date.now(),
    ]);
  }

  stmt.free();
  db.run('COMMIT');
  saveDatabase();
}

export function getMessagesByChannel(channelId, limit = 50) {
  const stmt = db.prepare(
    `SELECT * FROM messages
     WHERE channel_id = ?
     ORDER BY created_at DESC
     LIMIT ?`
  );

  stmt.bind([channelId, limit]);
  const results = [];

  while (stmt.step()) {
    const row = stmt.getAsObject();
    results.push(row);
  }

  stmt.free();
  return results;
}

export function getAllChannels() {
  const stmt = db.prepare(
    `SELECT DISTINCT channel_id, author_name as last_author
     FROM messages
     ORDER BY fetched_at DESC`
  );

  const results = [];
  while (stmt.step()) {
    results.push(stmt.getAsObject());
  }
  stmt.free();

  return results;
}

export function getLatestMessageTime(channelId) {
  const stmt = db.prepare(
    `SELECT MAX(created_at) as latest FROM messages WHERE channel_id = ?`
  );

  stmt.bind([channelId]);
  let result = null;

  if (stmt.step()) {
    result = stmt.getAsObject();
  }

  stmt.free();
  return result?.latest || 0;
}

export { db };
