const { describe, it, after } = require('node:test');
const assert = require('node:assert/strict');
const { db, inject, getToken, cleanup } = require('./setup');

after(() => cleanup());

describe('Auth', () => {
  it('registers a new user', async () => {
    const res = await inject('POST', '/api/auth/register', {
      email: 'auth1@test.com', password: 'pass123', name: 'Auth User'
    });
    assert.equal(res.status, 201);
    assert.ok(res.body.token);
    assert.equal(res.body.user.email, 'auth1@test.com');
  });

  it('rejects duplicate email', async () => {
    const res = await inject('POST', '/api/auth/register', {
      email: 'auth1@test.com', password: 'pass123', name: 'Dupe'
    });
    assert.equal(res.status, 409);
  });

  it('validates required fields', async () => {
    const res = await inject('POST', '/api/auth/register', { email: 'x@y.z' });
    assert.equal(res.status, 400);
  });

  it('validates email format', async () => {
    const res = await inject('POST', '/api/auth/register', {
      email: 'not-an-email', password: 'pass123', name: 'Bad'
    });
    assert.equal(res.status, 400);
  });

  it('validates password min length', async () => {
    const res = await inject('POST', '/api/auth/register', {
      email: 'short@test.com', password: '12345', name: 'Short'
    });
    assert.equal(res.status, 400);
  });

  it('logs in with correct credentials', async () => {
    const res = await inject('POST', '/api/auth/login', {
      email: 'auth1@test.com', password: 'pass123'
    });
    assert.equal(res.status, 200);
    assert.ok(res.body.token);
  });

  it('rejects wrong password', async () => {
    const res = await inject('POST', '/api/auth/login', {
      email: 'auth1@test.com', password: 'wrong'
    });
    assert.equal(res.status, 401);
  });

  it('GET /me returns user with valid token', async () => {
    const { token } = await getToken();
    const res = await inject('GET', '/api/auth/me', null, token);
    assert.equal(res.status, 200);
    assert.ok(res.body.id);
  });

  it('rejects request without token', async () => {
    const res = await inject('GET', '/api/auth/me');
    assert.equal(res.status, 401);
  });

  it('invalidates token after password change', async () => {
    // Register
    const reg = await inject('POST', '/api/auth/register', {
      email: 'pwchange@test.com', password: 'old_pass123', name: 'PW Test'
    });
    const oldToken = reg.body.token;

    // Change password
    const upd = await inject('PATCH', '/api/auth/profile', {
      currentPassword: 'old_pass123', newPassword: 'new_pass123'
    }, oldToken);
    assert.equal(upd.status, 200);
    const newToken = upd.body.token;

    // Old token should be rejected
    const res1 = await inject('GET', '/api/auth/me', null, oldToken);
    assert.equal(res1.status, 401);

    // New token should work
    const res2 = await inject('GET', '/api/auth/me', null, newToken);
    assert.equal(res2.status, 200);
  });
});
