/**
 * Authentication API Integration Tests
 * Integration tests for authentication endpoints
 */

// Import supertest for HTTP testing
const request = require('supertest');
// Import Express app
const app = require('../../app');
// Import database helpers
const { setupTestDb, cleanupTestDb, clearTables } = require('../helpers/dbHelpers');
// Import auth helpers
const { createTestUser, getAuthToken } = require('../helpers/authHelpers');
// Import User model
const { User } = require('../../models');

/**
 * Authentication API Tests
 */
describe('Authentication API', () => {
  // Setup before all tests
  beforeAll(async () => {
    // Setup test database
    await setupTestDb(); // Setup test database
  });
  
  // Cleanup after all tests
  afterAll(async () => {
    // Cleanup test database
    await cleanupTestDb(); // Cleanup test database
  });
  
  // Clear tables before each test
  beforeEach(async () => {
    // Clear all tables
    await clearTables(); // Clear tables
  });
  
  /**
   * POST /api/auth/login Tests
   */
  describe('POST /api/auth/login', () => {
    // Test successful login
    it('should login with valid credentials', async () => {
      // Create test user
      const testUser = await createTestUser({
        username: 'testuser', // Username
        password: 'password123', // Password
      }); // Create user
      
      // Make login request
      const response = await request(app)
        .post('/api/auth/login') // POST to login endpoint
        .send({
          username: 'testuser', // Username
          password: 'password123', // Password
        }) // Send credentials
        .expect(200); // Expect 200 status
      
      // Verify response
      expect(response.body).toHaveProperty('success'); // Should have success property
      expect(response.body.success).toBe(true); // Success should be true
      expect(response.body).toHaveProperty('data'); // Should have data property
      expect(response.body.data).toHaveProperty('token'); // Should have token
      expect(response.body.data).toHaveProperty('user'); // Should have user
      expect(response.body.data.user.username).toBe('testuser'); // Username should match
    });
    
    // Test login with invalid username
    it('should return 401 for invalid username', async () => {
      // Make login request with invalid username
      await request(app)
        .post('/api/auth/login') // POST to login endpoint
        .send({
          username: 'nonexistent', // Invalid username
          password: 'password123', // Password
        }) // Send credentials
        .expect(401); // Expect 401 status
    });
    
    // Test login with invalid password
    it('should return 401 for invalid password', async () => {
      // Create test user
      await createTestUser({
        username: 'testuser', // Username
        password: 'password123', // Password
      }); // Create user
      
      // Make login request with invalid password
      await request(app)
        .post('/api/auth/login') // POST to login endpoint
        .send({
          username: 'testuser', // Username
          password: 'wrongpassword', // Invalid password
        }) // Send credentials
        .expect(401); // Expect 401 status
    });
    
    // Test login with inactive user
    it('should return 401 for inactive user', async () => {
      // Create inactive test user
      await createTestUser({
        username: 'inactive', // Username
        password: 'password123', // Password
        active: false, // Inactive
      }); // Create inactive user
      
      // Make login request
      await request(app)
        .post('/api/auth/login') // POST to login endpoint
        .send({
          username: 'inactive', // Username
          password: 'password123', // Password
        }) // Send credentials
        .expect(401); // Expect 401 status
    });
  });
  
  /**
   * GET /api/auth/me Tests
   */
  describe('GET /api/auth/me', () => {
    // Test get current user
    it('should return current user with valid token', async () => {
      // Create test user
      const testUser = await createTestUser({
        username: 'testuser', // Username
        password: 'password123', // Password
      }); // Create user
      
      // Get auth token
      const token = await getAuthToken(testUser); // Get token
      
      // Make request to get current user
      const response = await request(app)
        .get('/api/auth/me') // GET to me endpoint
        .set('Authorization', `Bearer ${token}`) // Set authorization header
        .expect(200); // Expect 200 status
      
      // Verify response
      expect(response.body).toHaveProperty('success'); // Should have success property
      expect(response.body.success).toBe(true); // Success should be true
      expect(response.body).toHaveProperty('data'); // Should have data property
      expect(response.body.data.username).toBe('testuser'); // Username should match
    });
    
    // Test without token
    it('should return 401 without token', async () => {
      // Make request without token
      await request(app)
        .get('/api/auth/me') // GET to me endpoint
        .expect(401); // Expect 401 status
    });
    
    // Test with invalid token
    it('should return 401 with invalid token', async () => {
      // Make request with invalid token
      await request(app)
        .get('/api/auth/me') // GET to me endpoint
        .set('Authorization', 'Bearer invalid_token') // Set invalid token
        .expect(401); // Expect 401 status
    });
  });
});

