import { test } from 'node:test';
import assert from 'node:assert';
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
import { pool } from '../db/connection.js';

// Mock the database pool
const mockPool = {
  query: (sql, params) => {
    if (sql.includes('INSERT INTO users')) {
      return [{ insertId: 1 }];
    }
    if (sql.includes('SELECT id, email, password_hash FROM users')) {
      // Simulate a valid user with hashed password
      const hashedPassword = '$2a$12$O5y0793j8K4h6g7f9e8d7c6b5a4z3y2x1w0v9u8t7s6r5q4p3o2n1m';
      return [[{ id: 1, email: 'test@example.com', password_hash: hashedPassword }]];
    }
    return [];
  }
};

// Replace the actual pool with mock
const originalPool = pool;
pool.query = mockPool.query;

// Mock bcrypt.compare to always return true for valid password
const originalBcryptCompare = bcrypt.compare;
bcrypt.compare = async (password, hash) => {
  if (password === 'validpassword') {
    return true;
  }
  return false;
};

// Mock jwt.sign to return a fixed token
const originalJwtSign = jwt.sign;
jwt.sign = () => 'mock-jwt-token';

test('login should implement rate limiting for failed attempts', async () => {
  const req = {
    body: {
      email: 'test@example.com',
      password: 'wrongpassword'
    }
  };
  
  const res = {
    status: (code) => {
      res.statusCode = code;
      return res;
    },
    json: (data) => {
      res.data = data;
    }
  };

  // First 4 failed attempts should not be rate limited
  for (let i = 0; i < 4; i++) {
    await require('../routes/auth').default.post('/login', req, res);
    assert.strictEqual(res.statusCode, 401);
  }

  // 5th attempt should be rate limited
  await require('../routes/auth').default.post('/login', req, res);
  assert.strictEqual(res.statusCode, 429);
  assert.ok(res.data.error.includes('Too many login attempts'));
});

test('login should reset rate limit after successful authentication', async () => {
  const req = {
    body: {
      email: 'test@example.com',
      password: 'validpassword'
    }
  };
  
  const res = {
    status: (code) => {
      res.statusCode = code;
      return res;
    },
    json: (data) => {
      res.data = data;
    }
  };

  // Successful login should reset the rate limit
  await require('../routes/auth').default.post('/login', req, res);
  assert.strictEqual(res.statusCode, 200);
  
  // Now try to fail again - should not be rate limited immediately
  const failedReq = {
    body: {
      email: 'test@example.com',
      password: 'wrongpassword'
    }
  };
  
  await require('../routes/auth').default.post('/login', failedReq, res);
  assert.strictEqual(res.statusCode, 401);
});

// Restore the original functions
bcrypt.compare = originalBcryptCompare;
jwt.sign = originalJwtSign;
pool.query = originalPool;

export default {};