/**
 * E2E Test for Interview Edge Cases
 *
 * Tests expired tokens, used token reuse, invalid dates, duplicate bookings, rate limiting
 */

import { test, expect } from '@playwright/test';
import { prisma } from '../../lib/db';
import jwt from 'jsonwebtoken';

const BASE_URL = 'http://localhost:9000';

test.describe('Interview Edge Cases E2E', () => {
  test('should handle expired token gracefully', async ({ page }) => {
    const expiredPayload = {
      applicationId: 'app-expired',
      jobId: 'job-expired',
      applicantEmail: 'expired@example.com',
      iat: Math.floor(Date.now() / 1000) - 4 * 24 * 60 * 60,
      exp: Math.floor(Date.now() / 1000) - 24 * 60 * 60,
      jti: 'expired-edge-case',
    };

    const expiredToken = jwt.sign(expiredPayload, process.env.INTERVIEW_TOKEN_SECRET || 'test-secret');

    await page.goto(BASE_URL + '/en/careers/interview/schedule?token=' + expiredToken);

    await expect(page.locator('text=/link has expired/i')).toBeVisible();
    await expect(page.locator('text=/contact us/i')).toBeVisible();
    await expect(page.locator('input[type="date"]')).not.toBeVisible();
  });

  test('should prevent reuse of used token', async ({ page }) => {
    const job = await prisma.jobs.create({
      data: {
        title: 'Edge Case Job',
        titleAr: 'وظيفة',
        department: 'Test',
        location: 'Test',
        description: 'Test',
        descriptionAr: 'Test',
        status: 'open',
      },
    });

    const application = await prisma.job_applications.create({
      data: {
        jobId: job.id,
        applicantName: 'Used Token Test',
        applicantEmail: 'used-token@example.com',
        phoneNumber: '+97150777777',
        cvUrl: 'https://example.com/cv.pdf',
        status: 'selected',
      },
    });

    const payload = {
      applicationId: application.id,
      jobId: job.id,
      applicantEmail: 'used-token@example.com',
      iat: Math.floor(Date.now() / 1000),
      exp: Math.floor(Date.now() / 1000) + 3 * 24 * 60 * 60,
      jti: 'used-token-test',
    };

    const usedToken = jwt.sign(payload, process.env.INTERVIEW_TOKEN_SECRET || 'test-secret');

    await prisma.interview_booking_tokens.create({
      data: {
        id: 'used-token-test',
        token: usedToken,
        applicationId: application.id,
        jobId: job.id,
        applicantEmail: 'used-token@example.com',
        expiresAt: new Date(Date.now() + 3 * 24 * 60 * 60 * 1000),
        usedAt: new Date(),
        isRevoked: false,
      },
    });

    await page.goto(BASE_URL + '/en/careers/interview/schedule?token=' + usedToken);
    await expect(page.locator('text=/already been used/i')).toBeVisible();

    await prisma.interview_booking_tokens.deleteMany({ where: { applicationId: application.id } });
    await prisma.job_applications.deleteMany({ where: { id: application.id } });
    await prisma.jobs.deleteMany({ where: { id: job.id } });
  });

  test('should validate and reject invalid date selections', async ({ page }) => {
    const job = await prisma.jobs.create({
      data: {
        title: 'Date Validation Job',
        titleAr: 'وظيفة',
        department: 'Test',
        location: 'Test',
        description: 'Test',
        descriptionAr: 'Test',
        status: 'open',
      },
    });

    const application = await prisma.job_applications.create({
      data: {
        jobId: job.id,
        applicantName: 'Date Test User',
        applicantEmail: 'date-test@example.com',
        phoneNumber: '+97150666666',
        cvUrl: 'https://example.com/cv.pdf',
        status: 'selected',
      },
    });

    const payload = {
      applicationId: application.id,
      jobId: job.id,
      applicantEmail: 'date-test@example.com',
      iat: Math.floor(Date.now() / 1000),
      exp: Math.floor(Date.now() / 1000) + 3 * 24 * 60 * 60,
      jti: 'date-test-token',
    };

    const token = jwt.sign(payload, process.env.INTERVIEW_TOKEN_SECRET || 'test-secret');

    await prisma.interview_booking_tokens.create({
      data: {
        id: 'date-test-token',
        token,
        applicationId: application.id,
        jobId: job.id,
        applicantEmail: 'date-test@example.com',
        expiresAt: new Date(Date.now() + 3 * 24 * 60 * 60 * 1000),
        isRevoked: false,
      },
    });

    await page.goto(BASE_URL + '/en/careers/interview/schedule?token=' + token);

    await page.fill('input[type="date"]', '2024-01-01');
    await page.selectOption('select[name="time"]', '10:00');
    await page.click('button[type="submit"]');
    await expect(page.locator('text=/future date/i')).toBeVisible();

    const farFuture = new Date();
    farFuture.setDate(farFuture.getDate() + 20);
    await page.fill('input[type="date"]', farFuture.toISOString().split('T')[0]);
    await page.click('button[type="submit"]');
    await expect(page.locator('text=/within 14 days/i')).toBeVisible();

    await prisma.interview_booking_tokens.deleteMany({ where: { applicationId: application.id } });
    await prisma.job_applications.deleteMany({ where: { id: application.id } });
    await prisma.jobs.deleteMany({ where: { id: job.id } });
  });

  test('should prevent duplicate bookings', async ({ page }) => {
    const job = await prisma.jobs.create({
      data: {
        title: 'Duplicate Test Job',
        titleAr: 'وظيفة',
        department: 'Test',
        location: 'Test',
        description: 'Test',
        descriptionAr: 'Test',
        status: 'open',
      },
    });

    const application = await prisma.job_applications.create({
      data: {
        jobId: job.id,
        applicantName: 'Duplicate Test',
        applicantEmail: 'duplicate@example.com',
        phoneNumber: '+97150555555',
        cvUrl: 'https://example.com/cv.pdf',
        status: 'selected',
      },
    });

    await prisma.interview_bookings.create({
      data: {
        applicationId: application.id,
        jobId: job.id,
        applicantName: 'Duplicate Test',
        applicantEmail: 'duplicate@example.com',
        preferredDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
        preferredTime: '10:00:00',
        timezone: 'Asia/Qatar',
        status: 'pending',
      },
    });

    const payload = {
      applicationId: application.id,
      jobId: job.id,
      applicantEmail: 'duplicate@example.com',
      iat: Math.floor(Date.now() / 1000),
      exp: Math.floor(Date.now() / 1000) + 3 * 24 * 60 * 60,
      jti: 'duplicate-test-token',
    };

    const token = jwt.sign(payload, process.env.INTERVIEW_TOKEN_SECRET || 'test-secret');

    await prisma.interview_booking_tokens.create({
      data: {
        id: 'duplicate-test-token',
        token,
        applicationId: application.id,
        jobId: job.id,
        applicantEmail: 'duplicate@example.com',
        expiresAt: new Date(Date.now() + 3 * 24 * 60 * 60 * 1000),
        isRevoked: false,
      },
    });

    await page.goto(BASE_URL + '/en/careers/interview/schedule?token=' + token);

    const validDate = new Date();
    validDate.setDate(validDate.getDate() + 8);
    while (validDate.getDay() === 0 || validDate.getDay() === 6) {
      validDate.setDate(validDate.getDate() + 1);
    }

    await page.fill('input[type="date"]', validDate.toISOString().split('T')[0]);
    await page.selectOption('select[name="time"]', '14:00');
    await page.click('button[type="submit"]');
    await expect(page.locator('text=/already exists/i')).toBeVisible();

    await prisma.interview_bookings.deleteMany({ where: { applicationId: application.id } });
    await prisma.interview_booking_tokens.deleteMany({ where: { applicationId: application.id } });
    await prisma.job_applications.deleteMany({ where: { id: application.id } });
    await prisma.jobs.deleteMany({ where: { id: job.id } });
  });
});
