// src/tests/e2e/flyer-upload.e2e.test.ts
import { describe, it, expect, afterAll } from 'vitest';
import supertest from 'supertest';
import app from '../../../server';
import { getPool } from '../../services/db/connection.db';
import crypto from 'crypto';
import path from 'path';
import fs from 'fs';

/**
 * @vitest-environment node
 */

const request = supertest(app);

describe('E2E Flyer Upload and Processing Workflow', () => {
  const uniqueId = Date.now();
  const userEmail = `e2e-uploader-${uniqueId}@example.com`;
  const userPassword = 'StrongPassword123!';
  
  let authToken: string;
  let userId: string | null = null;
  let flyerId: number | null = null;

  afterAll(async () => {
    // Cleanup: Delete the flyer and user created during the test
    const pool = getPool();
    if (flyerId) {
      await pool.query('DELETE FROM public.flyers WHERE flyer_id = $1', [flyerId]);
    }
    if (userId) {
      await pool.query('DELETE FROM public.users WHERE user_id = $1', [userId]);
    }
  });

  it('should allow a user to upload a flyer and wait for processing to complete', async () => {
    // 1. Register a new user
    const registerResponse = await request.post('/api/auth/register').send({
      email: userEmail,
      password: userPassword,
      full_name: 'E2E Flyer Uploader',
    });
    expect(registerResponse.status).toBe(201);
    
    // 2. Login to get the access token
    const loginResponse = await request.post('/api/auth/login').send({
      email: userEmail,
      password: userPassword,
    });
    expect(loginResponse.status).toBe(200);
    authToken = loginResponse.body.token;
    userId = loginResponse.body.userprofile.user.user_id;
    expect(authToken).toBeDefined();

    // 3. Prepare the flyer file
    // We try to use the existing test asset if available, otherwise create a dummy buffer.
    // Note: In a real E2E scenario against a live AI service, a valid image is required.
    // If the AI service is mocked or stubbed in this environment, a dummy buffer might suffice.
    let fileBuffer: Buffer;
    let fileName = `e2e-test-flyer-${uniqueId}.jpg`;
    
    const assetPath = path.resolve(__dirname, '../assets/test-flyer-image.jpg');
    if (fs.existsSync(assetPath)) {
      const rawBuffer = fs.readFileSync(assetPath);
      // Append unique ID to ensure unique checksum for every test run
      fileBuffer = Buffer.concat([rawBuffer, Buffer.from(uniqueId.toString())]);
    } else {
      // Fallback to a minimal valid JPEG header + random data if asset is missing
      // (This might fail if the backend does strict image validation/processing)
      fileBuffer = Buffer.concat([
        Buffer.from([0xff, 0xd8, 0xff, 0xe0]), // JPEG Start of Image
        Buffer.from(uniqueId.toString())
      ]);
    }

    // Calculate checksum (required by the API)
    const checksum = crypto.createHash('sha256').update(fileBuffer).digest('hex');

    // 4. Upload the flyer
    const uploadResponse = await request
      .post('/api/ai/upload-and-process')
      .set('Authorization', `Bearer ${authToken}`)
      .field('checksum', checksum)
      .attach('flyerFile', fileBuffer, fileName);

    expect(uploadResponse.status).toBe(202);
    const jobId = uploadResponse.body.jobId;
    expect(jobId).toBeDefined();

    // 5. Poll for job completion
    let jobStatus;
    const maxRetries = 30; // Poll for up to 90 seconds
    for (let i = 0; i < maxRetries; i++) {
      await new Promise((resolve) => setTimeout(resolve, 3000)); // Wait 3s
      
      const statusResponse = await request
        .get(`/api/ai/jobs/${jobId}/status`)
        .set('Authorization', `Bearer ${authToken}`);
      
      jobStatus = statusResponse.body;
      if (jobStatus.state === 'completed' || jobStatus.state === 'failed') {
        break;
      }
    }

    expect(jobStatus.state).toBe('completed');
    flyerId = jobStatus.returnValue?.flyerId;
    expect(flyerId).toBeTypeOf('number');
  }, 120000); // Extended timeout for AI processing
});