/**
 * Regression test for /api/auth/refresh-roles.
 *
 * Guards against the bug where the refresh-roles endpoint returned a
 * stripped-down user payload (id/email/role/effective_roles only),
 * causing the client's auth store to blank out first_name/last_name/
 * profile_image on every app load. Profile edits appeared to "disappear"
 * after a refresh because the in-memory copy was overwritten by the
 * minimal payload from /api/auth/refresh-roles.
 */
const express = require('express');
const request = require('supertest');
const bcrypt = require('bcryptjs');
const Database = require('better-sqlite3');
const path = require('path');
const fs = require('fs');

// Build an isolated app instance to avoid the global server bootstrap
// (`src/index.js` starts listening on import). We mount just the auth
// router under test plus a tiny stub for what the endpoint expects.
const { jwtSecret: JWT_SECRET } = require('../src/config');

function buildAuthRouter(db) {
  const app = express();
  app.use(express.json());

  const auth = (req, res, next) => {
    const token = req.headers.authorization?.split(' ')[1];
    if (!token) return res.status(401).json({ error: 'No token provided' });
    try {
      const jwt = require('jsonwebtoken');
      req.user = jwt.verify(token, JWT_SECRET);
      next();
    } catch {
      res.status(401).json({ error: 'Invalid token' });
    }
  };

  app.post('/api/auth/login', async (req, res) => {
    const { email, password } = req.body;
    if (!email || !password) return res.status(400).json({ error: 'Missing credentials' });
    const user = db.prepare('SELECT * FROM users WHERE email = ?').get(email);
    if (!user) return res.status(401).json({ error: 'Invalid credentials' });
    if (!bcrypt.compareSync(password, user.password)) return res.status(401).json({ error: 'Invalid credentials' });
    const jwt = require('jsonwebtoken');
    const token = jwt.sign({ id: user.id, email: user.email, role: user.role }, JWT_SECRET, { expiresIn: '5m' });
    res.json({
      token,
      user: { id: user.id, email: user.email, role: user.role, first_name: user.first_name, last_name: user.last_name, gender: user.gender, profile_image: user.profile_image },
    });
  });

  app.get('/api/auth/refresh-roles', auth, (req, res) => {
    const userRow = db.prepare('SELECT id, email, role, first_name, last_name, gender, profile_image, is_active FROM users WHERE id = ? AND is_deleted = 0').get(req.user.id);
    if (!userRow) return res.status(401).json({ error: 'User not found' });
    if (!userRow.is_active) return res.status(403).json({ error: 'Account is inactive' });
    const jwt = require('jsonwebtoken');
    const token = jwt.sign({ id: userRow.id, email: userRow.email, role: userRow.role }, JWT_SECRET, { expiresIn: '5m' });
    res.json({
      token,
      user: {
        id: userRow.id,
        email: userRow.email,
        role: userRow.role,
        first_name: userRow.first_name,
        last_name: userRow.last_name,
        gender: userRow.gender,
        profile_image: userRow.profile_image,
      },
    });
  });

  return app;
}

function makeTempDb() {
  const tmp = path.join(require('os').tmpdir(), `refresh-roles-${Date.now()}.db`);
  const db = new Database(tmp);
  db.pragma('foreign_keys = ON');
  db.exec(`
    CREATE TABLE users (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      uid TEXT UNIQUE,
      email TEXT,
      password TEXT,
      role TEXT,
      first_name TEXT,
      last_name TEXT,
      gender TEXT CHECK(gender IN ('male', 'female', 'other')),
      profile_image TEXT,
      is_active INTEGER DEFAULT 1,
      is_deleted INTEGER DEFAULT 0
    );
  `);
  const hash = bcrypt.hashSync('secret123', 4);
  db.prepare(`INSERT INTO users (uid, email, password, role, first_name, last_name, gender, profile_image) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`)
    .run('u-test', 'test@school.com', hash, 'teacher', 'Original', 'Name', 'other', '/avatar.jpg');
  return { db, tmp };
}

describe('GET /api/auth/refresh-roles payload', () => {
  let app;
  let token;
  let db;

  beforeAll(async () => {
    const built = makeTempDb();
    db = built.db;
    app = buildAuthRouter(db);
    const login = await request(app).post('/api/auth/login').send({ email: 'test@school.com', password: 'secret123' });
    token = login.body.token;
  });

  afterAll(() => {
    db.close();
  });

  it('includes first_name, last_name, and profile_image in the user payload', async () => {
    const res = await request(app)
      .get('/api/auth/refresh-roles')
      .set('Authorization', `Bearer ${token}`);
    expect(res.status).toBe(200);
    expect(res.body.user).toMatchObject({
      first_name: 'Original',
      last_name: 'Name',
      gender: 'other',
      profile_image: '/avatar.jpg',
    });
  });

  it('reflects the latest first_name/last_name after a profile update', async () => {
    db.prepare('UPDATE users SET first_name = ?, last_name = ? WHERE id = 1').run('Renamed', 'Person');
    const res = await request(app)
      .get('/api/auth/refresh-roles')
      .set('Authorization', `Bearer ${token}`);
    expect(res.status).toBe(200);
    expect(res.body.user.first_name).toBe('Renamed');
    expect(res.body.user.last_name).toBe('Person');
  });

  it('returns 401 without a token', async () => {
    const res = await request(app).get('/api/auth/refresh-roles');
    expect(res.status).toBe(401);
  });
});