#!/usr/bin/env node
/**
 * Deterministic scratch DB for the E2E suite (docs/QA_PLAN.md §4.4).
 *
 * Creates a throwaway SQLite DB, a regular `user` with known creds, and seeds
 * realistic demo data for that user — so `npm run test:e2e` is safe to run:
 * it NEVER touches the real db/bills.db. Runs fresh every invocation.
 */
const path = require('path');
const fs = require('fs');
const bcrypt = require('bcryptjs');
const { E2E_USER, E2E_PASS, scratchDbPath } = require('../constants');

const REAL_DB = path.join(__dirname, '..', '..', 'db', 'bills.db');
const dbPath = scratchDbPath();

// Safety rail: refuse to operate on the real database.
if (path.resolve(dbPath) === path.resolve(REAL_DB)) {
  console.error(`[e2e] Refusing to use the real DB at ${REAL_DB}. Set E2E_DB_PATH to a scratch path.`);
  process.exit(1);
}

// Start from a clean slate so every run is reproducible.
for (const suffix of ['', '-wal', '-shm']) {
  const f = dbPath + suffix;
  if (fs.existsSync(f)) fs.rmSync(f);
}
fs.mkdirSync(path.dirname(dbPath), { recursive: true });

// db/database.js reads DB_PATH at require-time — set it BEFORE requiring.
process.env.DB_PATH = dbPath;
const { getDb, ensureUserDefaultCategories } = require('../../db/database');
const { seedDemoData } = require('../../scripts/seedDemoData');

const db = getDb(); // initializes schema + runs migrations

// Regular `user` (role 'user', no forced password change) — mirrors the app's
// own INIT_REGULAR_USER seed path in server.js.
let user = db.prepare('SELECT id FROM users WHERE username = ?').get(E2E_USER);
if (!user) {
  const hash = bcrypt.hashSync(E2E_PASS, 12);
  const res = db
    .prepare(
      `INSERT INTO users (username, password_hash, role, first_login, must_change_password, is_default_admin)
       VALUES (?, ?, 'user', 0, 0, 0)`,
    )
    .run(E2E_USER, hash);
  user = { id: Number(res.lastInsertRowid) };
}
ensureUserDefaultCategories(user.id);

// Seed demo bills/categories for this user (idempotent).
const result = seedDemoData(user.id);

// Second user (role 'user') with their OWN seeded data — the IDOR target for the
// data-isolation probe (e2e/api.probe.spec.js). User A must not be able to
// read/modify any of user B's resources.
const E2E_USER_B = 'e2e_user_b';
let userB = db.prepare('SELECT id FROM users WHERE username = ?').get(E2E_USER_B);
if (!userB) {
  const hashB = bcrypt.hashSync(E2E_PASS, 12);
  const resB = db
    .prepare(
      `INSERT INTO users (username, password_hash, role, first_login, must_change_password, is_default_admin)
       VALUES (?, ?, 'user', 0, 0, 0)`,
    )
    .run(E2E_USER_B, hashB);
  userB = { id: Number(resB.lastInsertRowid) };
}
ensureUserDefaultCategories(userB.id);
seedDemoData(userB.id);
const billB = db.prepare('SELECT id FROM bills WHERE user_id = ? ORDER BY id LIMIT 1').get(userB.id);

// Fixture consumed by the probe spec (git-ignored under e2e/.auth/).
const fixturePath = path.join(__dirname, '..', '.auth', 'fixture.json');
fs.mkdirSync(path.dirname(fixturePath), { recursive: true });
fs.writeFileSync(
  fixturePath,
  JSON.stringify({ userAId: user.id, userBId: userB.id, userBBillId: billB ? billB.id : null }, null, 2),
);

console.log(`[e2e] Scratch DB ready at ${dbPath}`);
console.log(`[e2e] User A '${E2E_USER}' (id=${user.id}) — ${JSON.stringify(result)}`);
console.log(`[e2e] User B '${E2E_USER_B}' (id=${userB.id}) — IDOR target bill id=${billB ? billB.id : 'none'}`);
