// src/tests/integration/user.routes.integration.test.ts
import { describe, it, expect, beforeAll } from 'vitest';
import supertest from 'supertest';

const API_URL = process.env.VITE_API_BASE_URL || 'http://localhost:3001/api';
const request = supertest(API_URL.replace('/api', '')); // supertest needs the server's base URL

let authToken = '';
let createdListId: number;

describe('User Routes Integration Tests (/api/users)', () => {
  // Authenticate once before all tests in this suite to get a JWT.
  beforeAll(async () => {
    const loginResponse = await request
      .post('/api/auth/login')
      .send({
        email: process.env.ADMIN_EMAIL || 'admin@test.com',
        password: process.env.ADMIN_PASSWORD || 'password',
      });
    
    if (loginResponse.status !== 200) {
      console.error('Login failed in beforeAll hook:', loginResponse.body);
    }
    
    expect(loginResponse.status).toBe(200);
    expect(loginResponse.body.token).toBeDefined();
    authToken = loginResponse.body.token;
  });

  describe('GET /api/users/profile', () => {
    it('should return the profile for the authenticated user', async () => {
      const response = await request
        .get('/api/users/profile')
        .set('Authorization', `Bearer ${authToken}`);

      expect(response.status).toBe(200);
      expect(response.body).toBeDefined();
      expect(response.body.email).toBe(process.env.ADMIN_EMAIL || 'admin@test.com');
      expect(response.body.role).toBe('admin');
    });

    it('should return 401 Unauthorized if no token is provided', async () => {
      const response = await request.get('/api/users/profile');
      expect(response.status).toBe(401);
    });
  });

  describe('PUT /api/users/profile', () => {
    it('should update the user profile', async () => {
      const newName = `Test User ${Date.now()}`;
      const response = await request
        .put('/api/users/profile')
        .set('Authorization', `Bearer ${authToken}`)
        .send({ full_name: newName });

      expect(response.status).toBe(200);
      expect(response.body.full_name).toBe(newName);

      // Verify the change by fetching the profile again
      const verifyResponse = await request
        .get('/api/users/profile')
        .set('Authorization', `Bearer ${authToken}`);
      
      expect(verifyResponse.body.full_name).toBe(newName);
    });
  });

  describe('Shopping List CRUD', () => {
    it('POST /api/users/shopping-lists should create a new shopping list', async () => {
      const listName = `My Integration Test List ${Date.now()}`;
      const response = await request
        .post('/api/users/shopping-lists')
        .set('Authorization', `Bearer ${authToken}`)
        .send({ name: listName });

      expect(response.status).toBe(201);
      expect(response.body.name).toBe(listName);
      expect(response.body.shopping_list_id).toBeDefined();
      createdListId = response.body.shopping_list_id; // Save for the next test
    });

    it('GET /api/users/shopping-lists should retrieve the created shopping list', async () => {
      const response = await request
        .get('/api/users/shopping-lists')
        .set('Authorization', `Bearer ${authToken}`);

      expect(response.status).toBe(200);
      expect(Array.isArray(response.body)).toBe(true);
      const foundList = response.body.find((list: { shopping_list_id: number; }) => list.shopping_list_id === createdListId);
      expect(foundList).toBeDefined();
    });

    it('DELETE /api/users/shopping-lists/:listId should delete the shopping list', async () => {
      expect(createdListId).toBeDefined(); // Ensure the previous test ran and set the ID

      const response = await request
        .delete(`/api/users/shopping-lists/${createdListId}`)
        .set('Authorization', `Bearer ${authToken}`);

      expect(response.status).toBe(204);

      // Verify deletion
      const verifyResponse = await request
        .get('/api/users/shopping-lists')
        .set('Authorization', `Bearer ${authToken}`);
      
      const foundList = verifyResponse.body.find((list: { shopping_list_id: number; }) => list.shopping_list_id === createdListId);
      expect(foundList).toBeUndefined();
    });
  });

  describe('PUT /api/users/profile/preferences', () => {
    it('should update user preferences', async () => {
      const preferences = { darkMode: true, unitSystem: 'metric' };
      const response = await request
        .put('/api/users/profile/preferences')
        .set('Authorization', `Bearer ${authToken}`)
        .send(preferences);

      expect(response.status).toBe(200);
      expect(response.body.preferences).toEqual(preferences);

      // Verify the change by fetching the profile again
      const verifyResponse = await request
        .get('/api/users/profile')
        .set('Authorization', `Bearer ${authToken}`);
      
      expect(verifyResponse.body.preferences.darkMode).toBe(true);
      expect(verifyResponse.body.preferences.unitSystem).toBe('metric');
    });
  });
});