const test = require('node:test');
const assert = require('assert');
const { app } = require('../app');

test('GET /reviews should return all reviews', async () => {
  const response = await app.inject({
    method: 'GET',
    url: '/reviews'
  });
  
  assert.strictEqual(response.statusCode, 200);
  assert.strictEqual(response.headers['content-type'], 'application/json; charset=utf-8');
});

test('POST /reviews should create a new review', async () => {
  const newReview = {
    dealId: 1,
    revieweeId: 2,
    rating: 5,
    comment: 'Great product'
  };
  
  const response = await app.inject({
    method: 'POST',
    url: '/reviews/1',
    payload: newReview
  });
  
  assert.strictEqual(response.statusCode, 201);
  assert.strictEqual(response.headers['content-type'], 'application/json; charset=utf-8');
});

test('POST /reviews should return 400 for invalid review data', async () => {
  const invalidReview = {
    dealId: 1,
    revieweeId: 2,
    rating: 6,
    comment: 'Some content'
  };
  
  const response = await app.inject({
    method: 'POST',
    url: '/reviews/1',
    payload: invalidReview
  });
  
  assert.strictEqual(response.statusCode, 400);
});

test('POST /reviews should return 404 for non-existent deal', async () => {
  const newReview = {
    dealId: 999,
    revieweeId: 2,
    rating: 5,
    comment: 'Great product'
  };
  
  const response = await app.inject({
    method: 'POST',
    url: '/reviews/999',
    payload: newReview
  });
  
  assert.strictEqual(response.statusCode, 404);
});

test('POST /reviews should return 409 for already reviewed deal', async () => {
  const newReview = {
    dealId: 1,
    revieweeId: 2,
    rating: 5,
    comment: 'Great product'
  };
  
  // First submission
  await app.inject({
    method: 'POST',
    url: '/reviews/1',
    payload: newReview
  });
  
  // Second submission - should fail
  const response = await app.inject({
    method: 'POST',
    url: '/reviews/1',
    payload: newReview
  });
  
  assert.strictEqual(response.statusCode, 409);
});

test('POST /reviews should return 400 for invalid dealId', async () => {
  const newReview = {
    dealId: 'invalid',
    revieweeId: 2,
    rating: 5,
    comment: 'Great product'
  };
  
  const response = await app.inject({
    method: 'POST',
    url: '/reviews/invalid',
    payload: newReview
  });
  
  assert.strictEqual(response.statusCode, 400);
});

test('POST /reviews should return 400 for invalid revieweeId', async () => {
  const newReview = {
    dealId: 1,
    revieweeId: -1,
    rating: 5,
    comment: 'Great product'
  };
  
  const response = await app.inject({
    method: 'POST',
    url: '/reviews/1',
    payload: newReview
  });
  
  assert.strictEqual(response.statusCode, 400);
});

test('POST /reviews should return 400 for invalid rating', async () => {
  const newReview = {
    dealId: 1,
    revieweeId: 2,
    rating: 0,
    comment: 'Great product'
  };
  
  const response = await app.inject({
    method: 'POST',
    url: '/reviews/1',
    payload: newReview
  });
  
  assert.strictEqual(response.statusCode, 400);
});

test('POST /reviews should return 400 for invalid comment length', async () => {
  const newReview = {
    dealId: 1,
    revieweeId: 2,
    rating: 5,
    comment: 'a'.repeat(2001)
  };
  
  const response = await app.inject({
    method: 'POST',
    url: '/reviews/1',
    payload: newReview
  });
  
  assert.strictEqual(response.statusCode, 400);
});

test('POST /reviews should return 400 for missing revieweeId', async () => {
  const newReview = {
    dealId: 1,
    rating: 5,
    comment: 'Great product'
  };
  
  const response = await app.inject({
    method: 'POST',
    url: '/reviews/1',
    payload: newReview
  });
  
  assert.strictEqual(response.statusCode, 400);
});

test('POST /reviews should return 400 for missing rating', async () => {
  const newReview = {
    dealId: 1,
    revieweeId: 2,
    comment: 'Great product'
  };
  
  const response = await app.inject({
    method: 'POST',
    url: '/reviews/1',
    payload: newReview
  });
  
  assert.strictEqual(response.statusCode, 400);
});

// Additional test for valid dealId (number)
test('POST /reviews should accept valid numeric dealId', async () => {
  const newReview = {
    dealId: 1,
    revieweeId: 2,
    rating: 5,
    comment: 'Great product'
  };
  
  const response = await app.inject({
    method: 'POST',
    url: '/reviews/1',
    payload: newReview
  });
  
  assert.strictEqual(response.statusCode, 201);
});

// Additional test for valid dealId (string number)
test('POST /reviews should accept valid string numeric dealId', async () => {
  const newReview = {
    dealId: '1',
    revieweeId: 2,
    rating: 5,
    comment: 'Great product'
  };
  
  const response = await app.inject({
    method: 'POST',
    url: '/reviews/1',
    payload: newReview
  });
  
  assert.strictEqual(response.statusCode, 201);
});