import Database from 'better-sqlite3';
import bcrypt from 'bcrypt';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import { readFileSync } from 'fs';

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

const DB_PATH = join(__dirname, 'kenteken.db');

let db;

export function initDb() {
  db = new Database(DB_PATH);
  db.pragma('journal_mode = WAL');
  db.pragma('foreign_keys = ON');

  db.exec(`
    CREATE TABLE IF NOT EXISTS cars (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      width REAL NOT NULL,
      height REAL NOT NULL,
      rearWidth REAL,
      rearHeight REAL
    )
  `);

  db.exec(`
    CREATE TABLE IF NOT EXISTS settings (
      key TEXT PRIMARY KEY,
      value TEXT NOT NULL
    )
  `);

  // Seed the database with default cars if empty
  const count = db.prepare('SELECT COUNT(*) as cnt FROM cars').get();
  if (count.cnt === 0) {
    seedDefaultCars();
  }

  // Set default admin password if not set
  const pwd = db.prepare("SELECT value FROM settings WHERE key = 'admin_password'").get();
  if (!pwd) {
    const hash = bcrypt.hashSync('Rotterdam-010', 10);
    db.prepare("INSERT INTO settings (key, value) VALUES ('admin_password', ?)").run(hash);
  }
}

function seedDefaultCars() {
  const defaultCarsPath = join(__dirname, 'carOptions.json');
  let defaultCars;
  try {
    defaultCars = JSON.parse(readFileSync(defaultCarsPath, 'utf-8'));
  } catch {
    defaultCars = [];
  }

  const insert = db.prepare(
    'INSERT INTO cars (name, width, height, rearWidth, rearHeight) VALUES (?, ?, ?, ?, ?)'
  );
  const insertMany = db.transaction((cars) => {
    for (const car of cars) {
      insert.run(car.name, car.width, car.height, car.rearWidth || null, car.rearHeight || null);
    }
  });
  insertMany(defaultCars);
}

export function getAllCars() {
  return db.prepare('SELECT * FROM cars ORDER BY name COLLATE NOCASE').all();
}

export function addCar({ name, width, height, rearWidth, rearHeight }) {
  const result = db.prepare(
    'INSERT INTO cars (name, width, height, rearWidth, rearHeight) VALUES (?, ?, ?, ?, ?)'
  ).run(name, width, height, rearWidth, rearHeight);
  return db.prepare('SELECT * FROM cars WHERE id = ?').get(result.lastInsertRowid);
}

export function updateCar(id, { name, width, height, rearWidth, rearHeight }) {
  const result = db.prepare(
    'UPDATE cars SET name = ?, width = ?, height = ?, rearWidth = ?, rearHeight = ? WHERE id = ?'
  ).run(name, width, height, rearWidth, rearHeight, id);
  if (result.changes === 0) return null;
  return db.prepare('SELECT * FROM cars WHERE id = ?').get(id);
}

export function deleteCar(id) {
  const result = db.prepare('DELETE FROM cars WHERE id = ?').run(id);
  return result.changes > 0;
}

export function replaceAllCars(cars) {
  const tx = db.transaction(() => {
    db.prepare('DELETE FROM cars').run();
    const insert = db.prepare(
      'INSERT INTO cars (name, width, height, rearWidth, rearHeight) VALUES (?, ?, ?, ?, ?)'
    );
    for (const car of cars) {
      insert.run(
        String(car.name || '').trim(),
        Number(car.width) || 0,
        Number(car.height) || 0,
        car.rearWidth ? Number(car.rearWidth) : null,
        car.rearHeight ? Number(car.rearHeight) : null
      );
    }
  });
  tx();
}

export function verifyPassword(password) {
  const row = db.prepare("SELECT value FROM settings WHERE key = 'admin_password'").get();
  if (!row) return false;
  return bcrypt.compareSync(password, row.value);
}
