const request = require('supertest');
const app = require('../src/server');

describe('Health', () => {
  it('GET /health returns ok', async () => {
    const res = await request(app).get('/health');
    expect(res.status).toBe(200);
    expect(res.body.status).toBe('ok');
    expect(res.body.service).toBe('lms-bgn-backend');
  });
});

describe('Epik 1 - Courses', () => {
  it('GET /api/courses returns paged list', async () => {
    const res = await request(app).get('/api/courses?page=1&pageSize=20');
    expect(res.status).toBe(200);
    expect(res.body).toHaveProperty('page');
    expect(res.body).toHaveProperty('pageSize');
    expect(res.body).toHaveProperty('total');
    expect(Array.isArray(res.body.items)).toBe(true);
  });

  it('GET /api/courses/:courseId returns detail', async () => {
    const res = await request(app).get('/api/courses/c1');
    expect(res.status).toBe(200);
    expect(res.body.id).toBe('c1');
    expect(res.body).toHaveProperty('modules');
  });

  it('GET /api/courses/:courseId returns 404 for unknown', async () => {
    const res = await request(app).get('/api/courses/unknown');
    expect(res.status).toBe(404);
  });

  it('POST /api/modules/:moduleId/progress validates progressPercent', async () => {
    const res = await request(app)
      .post('/api/modules/m1/progress')
      .send({ progressPercent: 50 });
    expect(res.status).toBe(202);
    expect(res.body.status).toBe('accepted');
  });
});

describe('Epik 1 - Assignments', () => {
  it('POST /api/assignments/:assignmentId/submission requires idempotencyKey', async () => {
    const res = await request(app)
      .post('/api/assignments/a1/submission')
      .send({ content: 'Answer' });
    expect(res.status).toBe(400);
  });

  it('POST /api/assignments/:assignmentId/submission creates submission', async () => {
    const res = await request(app)
      .post('/api/assignments/a1/submission')
      .send({ content: 'Answer', idempotencyKey: 'abc' });
    expect(res.status).toBe(201);
    expect(res.body.status).toBe('created');
  });

  it('POST /api/assignments/:assignmentId/submission returns 409 on duplicate idempotency', async () => {
    await request(app)
      .post('/api/assignments/a1/submission')
      .send({ content: 'Answer', idempotencyKey: 'dup-key' });
    const res = await request(app)
      .post('/api/assignments/a1/submission')
      .send({ content: 'Answer', idempotencyKey: 'dup-key' });
    expect(res.status).toBe(409);
  });
});

describe('Epik 2 - Exam Session', () => {
  let sessionId;

  it('POST /api/exam-session requires fields', async () => {
    const res = await request(app)
      .post('/api/exam-session')
      .set('Authorization', 'Bearer test-token')
      .send({});
    expect(res.status).toBe(400);
  });

  it('POST /api/exam-session creates session', async () => {
    const res = await request(app)
      .post('/api/exam-session')
      .set('Authorization', 'Bearer test-token')
      .send({ examId: 'exam-001', userId: 'u1' });
    expect(res.status).toBe(201);
    expect(res.body).toHaveProperty('sessionId');
    sessionId = res.body.sessionId;
  });

  it('POST /api/exam-session/:sessionId/score scores answers', async () => {
    const res = await request(app)
      .post(`/api/exam-session/${sessionId}/score`)
      .set('Authorization', 'Bearer test-token')
      .send({
        idempotencyKey: 'score-1',
        mode: 'batch',
        answers: [
          { questionId: 'q1', choiceIndex: 0 },
          { questionId: 'q2', choiceIndex: 2 }
        ]
      });
    expect(res.status).toBe(200);
    expect(res.body).toHaveProperty('totalScore');
    expect(res.body).toHaveProperty('totalQuestions');
    expect(res.body).toHaveProperty('correctAnswers');
  });

  it('POST /api/exam-session/:sessionId/score returns 409 on duplicate idempotency', async () => {
    const res = await request(app)
      .post(`/api/exam-session/${sessionId}/score`)
      .set('Authorization', 'Bearer test-token')
      .send({ idempotencyKey: 'score-1', answers: [] });
    expect(res.status).toBe(409);
  });

  it('GET /api/exam-session/:sessionId/summary returns summary', async () => {
    const res = await request(app)
      .get(`/api/exam-session/${sessionId}/summary`)
      .set('Authorization', 'Bearer test-token');
    expect(res.status).toBe(200);
    expect(res.body).toHaveProperty('examId');
    expect(res.body).toHaveProperty('answers');
  });
});

describe('Epik 2 - Exams listing', () => {
  it('GET /api/exams returns paged list', async () => {
    const res = await request(app).get('/api/exams?page=1&pageSize=20');
    expect(res.status).toBe(200);
    expect(res.body).toHaveProperty('items');
  });

  it('GET /api/exams filters by q', async () => {
    const res = await request(app).get('/api/exams?page=1&pageSize=20&q=HACCP');
    expect(res.status).toBe(200);
    expect(Array.isArray(res.body.items)).toBe(true);
  });
});

describe('Epik 2 - Certificates', () => {
  it('POST /api/certificates/:certificateId/resend requires fields', async () => {
    let res = await request(app)
      .post('/api/certificates/abc/resend')
      .send({ idempotencyKey: 'id1' });
    expect(res.status).toBe(400);

    res = await request(app)
      .post('/api/certificates/abc/resend')
      .send({ recipientEmail: 'x@y.com' });
    expect(res.status).toBe(400);
  });

  it('POST /api/certificates/:certificateId/resend accepts and throttles', async () => {
    const res1 = await request(app)
      .post('/api/certificates/abc/resend')
      .send({ recipientEmail: 'x@y.com', idempotencyKey: 'cert-1' });
    expect(res1.status).toBe(202);

    const res2 = await request(app)
      .post('/api/certificates/abc/resend')
      .send({ recipientEmail: 'x@y.com', idempotencyKey: 'cert-1' });
    expect(res2.status).toBe(429);
  });
});