/**
 * E2E Tests: Company Info Submission
 *
 * These tests catch the "Failed to save company information" bug
 * from a user's perspective by simulating the complete signup flow
 */

import { test, expect } from '@playwright/test';
import { prisma } from '@/lib/db';
import { randomUUID } from 'crypto';

// UUID generator
const generateUUID = () => randomUUID();

test.describe('Company Info Submission - E2E', () => {
  const testEmail = `test-${Date.now()}@example.com`;
  const testData = {
    fullName: 'Test User',
    companyName: 'Shelton and Cobb Traders',
    industry: 'education',
    companySize: '11-50 employees',
    gccCountry: 'United Arab Emirates',
    phoneNumber: '+971 (621) 387-5038',
    agentCount: '3-5 agents',
    services: ['Booking Automation', 'Deposits & Payments', 'Reminders & Reschedule'],
  };

  test.beforeEach(async ({ page }) => {
    // Start fresh
    await page.goto('http://localhost:9000/en/signup');
  });

  test.afterEach(async () => {
    // Cleanup test data
    try {
      await prisma.users.deleteMany({
        where: { email: testEmail },
      });
    } catch (error) {
      console.log('Cleanup error:', error);
    }
  });

  /**
   * BUG PREVENTION #1: Complete Flow Test
   *
   * Tests the entire flow to catch integration issues
   */
  test('should complete full signup flow and save company info', async ({ page }) => {
    // Step 1: Select package (skip if already on info page)
    const hasPackageButton = await page.locator('button:has-text("Continue to Sign Up")').count();
    if (hasPackageButton > 0) {
      await page.click('button:has-text("Professional")');
      await page.click('button:has-text("Continue to Sign Up")');
    }

    // Step 2: Enter email and name
    await page.fill('input[id="fullName"]', testData.fullName);
    await page.fill('input[id="email"]', testEmail);
    await page.click('button[type="submit"]:has-text("Send Verification Code")');

    // Step 3: Wait for verify page
    await page.waitForURL(/.*\/signup\/verify/);

    // Get OTP from MailHog
    const mailhogResponse = await page.request.get('http://localhost:8025/api/v2/messages');
    const messages = await mailhogResponse.json();
    const latestMessage = messages.items?.[0];

    expect(latestMessage).toBeDefined();
    expect(latestMessage.Content.Headers.To[0]).toContain(testEmail);

    // Extract OTP from email
    const emailBody = latestMessage.Content.Body;
    const otpMatch = emailBody.match(/\b\d{6}\b/);
    expect(otpMatch).toBeTruthy();
    const otp = otpMatch![0];

    // Step 4: Enter OTP
    const otpDigits = otp.split('');
    for (let i = 0; i < 6; i++) {
      await page.fill(`input[data-index="${i}"]`, otpDigits[i]);
    }

    // Wait for redirect to company info page
    await page.waitForURL(/.*\/signup\/company-info/, { timeout: 10000 });

    // Step 5: Fill company information form
    await page.fill('input[id="companyName"]', testData.companyName);
    await page.selectOption('select[id="industry"]', 'education');
    await page.selectOption('select[id="companySize"]', '11-50');
    await page.selectOption('select[id="gccCountry"]', 'uae');
    await page.fill('input[id="phoneNumber"]', testData.phoneNumber);
    await page.fill('input[id="agentCount"]', testData.agentCount);

    // Select services
    for (const service of testData.services) {
      const serviceLabel = page.locator(`label:has-text("${service}")`);
      await serviceLabel.click();
    }

    // Step 6: Submit form
    await page.click('button[type="submit"]:has-text("Continue")');

    // Step 7: Verify no error message appears
    const errorMessage = page.locator('div:has-text("Failed to save company information")');
    await expect(errorMessage).not.toBeVisible({ timeout: 5000 });

    // Step 8: Should redirect to onboarding/goals page
    await page.waitForURL(/.*\/signup\/onboarding/, { timeout: 10000 });

    // Step 9: Verify data was saved to database
    const savedUser = await prisma.users.findUnique({
      where: { email: testEmail },
      include: {
        audit_logs: {
          where: { type: 'company_info_update' },
          orderBy: { createdAt: 'desc' },
          take: 1,
        },
      },
    });

    expect(savedUser).toBeDefined();
    expect(savedUser!.companyName).toBe(testData.companyName);
    expect(savedUser!.industry).toBe('education');
    expect(savedUser!.companySize).toBe('11-50');
    expect(savedUser!.country).toBe('uae');
    expect(savedUser!.phoneNumber).toContain('387-5038');

    // Verify audit log has an ID
    expect(savedUser!.audit_logs).toHaveLength(1);
    expect(savedUser!.audit_logs[0].id).toBeDefined();
    expect(savedUser!.audit_logs[0].id).toMatch(
      /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
    );
  });

  /**
   * BUG PREVENTION #2: Validation Error Display
   *
   * Ensures users see helpful error messages
   */
  test('should display specific validation errors for invalid data', async ({ page }) => {
    // Navigate directly to company info (simulate user resuming)
    await page.goto('http://localhost:9000/en/signup/company-info');

    // Try to submit with empty required fields
    await page.click('button[type="submit"]:has-text("Continue")');

    // Should show field-specific errors
    await expect(page.locator('text=Company name is required')).toBeVisible();
    await expect(page.locator('text=Please select an industry')).toBeVisible();
    await expect(page.locator('text=Please select company size')).toBeVisible();
    await expect(page.locator('text=Please select country')).toBeVisible();
  });

  /**
   * BUG PREVENTION #3: Phone Number Format Handling
   *
   * Tests various phone number formats
   */
  test('should accept various phone number formats', async ({ page }) => {
    // This test verifies phone validation doesn't reject valid formats
    const phoneFormats = [
      '+971501234567',
      '+971 50 123 4567',
      '+971 (50) 123-4567',
      '0501234567',
    ];

    for (const phoneFormat of phoneFormats) {
      await page.goto('http://localhost:9000/en/signup/company-info');

      await page.fill('input[id="phoneNumber"]', phoneFormat);

      // Validate phone field doesn't show error
      const phoneError = page.locator('text=Invalid phone number');
      await expect(phoneError).not.toBeVisible();
    }
  });

  /**
   * BUG PREVENTION #4: Services Selection
   *
   * Ensures multi-select services work correctly
   */
  test('should handle multiple service selections', async ({ page }) => {
    await page.goto('http://localhost:9000/en/signup/company-info');

    // Select multiple services
    await page.click('label:has-text("Booking Automation")');
    await page.click('label:has-text("Deposits & Payments")');
    await page.click('label:has-text("Reminders & Reschedule")');

    // Verify services are selected (checkboxes checked)
    await expect(page.locator('input[type="checkbox"]:checked')).toHaveCount(3);

    // Verify count indicator
    await expect(page.locator('text=3 service(s) selected')).toBeVisible();
  });

  /**
   * BUG PREVENTION #5: Network Error Handling
   *
   * Tests error handling when API is unavailable
   */
  test('should show error message when API request fails', async ({ page }) => {
    await page.goto('http://localhost:9000/en/signup/company-info');

    // Intercept API call and simulate failure
    await page.route('**/api/onboarding/company-info', async (route) => {
      await route.fulfill({
        status: 500,
        contentType: 'application/json',
        body: JSON.stringify({
          error: 'Database connection failed',
        }),
      });
    });

    // Fill form with valid data
    await page.fill('input[id="companyName"]', testData.companyName);
    await page.selectOption('select[id="industry"]', 'education');
    await page.selectOption('select[id="companySize"]', '11-50');
    await page.selectOption('select[id="gccCountry"]', 'uae');
    await page.fill('input[id="phoneNumber"]', testData.phoneNumber);
    await page.fill('input[id="agentCount"]', '3-5');

    // Submit form
    await page.click('button[type="submit"]:has-text("Continue")');

    // Should show error message
    await expect(page.locator('text=Database connection failed')).toBeVisible({
      timeout: 5000,
    });
  });

  /**
   * BUG PREVENTION #6: Missing User Scenario
   *
   * Tests error when user hasn't completed signup
   */
  test('should redirect when user has not completed signup', async ({ page }) => {
    // Clear localStorage to simulate missing signup data
    await page.goto('http://localhost:9000/en/signup/company-info');
    await page.evaluate(() => localStorage.clear());
    await page.reload();

    // Fill and submit form
    await page.fill('input[id="companyName"]', testData.companyName);
    await page.selectOption('select[id="industry"]', 'education');
    await page.selectOption('select[id="companySize"]', '11-50');
    await page.selectOption('select[id="gccCountry"]', 'uae');
    await page.fill('input[id="phoneNumber"]', testData.phoneNumber);
    await page.fill('input[id="agentCount"]', '3-5');

    await page.click('button[type="submit"]:has-text("Continue")');

    // Should show error and redirect
    await expect(
      page.locator('text=You must complete the signup steps first')
    ).toBeVisible({ timeout: 3000 });

    // Should redirect to signup page
    await page.waitForURL(/.*\/signup$/, { timeout: 5000 });
  });

  /**
   * BUG PREVENTION #7: Dual Database Consistency
   *
   * Verifies data is saved to both Prisma and Supabase
   */
  test('should save company info to both databases', async ({ page }) => {
    // Complete signup flow (abbreviated version for this test)
    await page.goto('http://localhost:9000/en/signup');

    // Mock OTP verification by creating user directly
    const userId = generateUUID();
    await prisma.users.create({
      data: {
        id: userId,
        email: testEmail,
        name: testData.fullName,
        emailVerified: new Date(),
        createdAt: new Date(),
        updatedAt: new Date(),
      },
    });

    // Set signup data in localStorage
    await page.evaluate(
      ({ email, userId }) => {
        localStorage.setItem(
          'signupData',
          JSON.stringify({
            email,
            userId,
            fullName: 'Test User',
            plan: { tierId: 'tier2', billingPeriod: 'monthly', currency: 'AED' },
            verified: true,
          })
        );
      },
      { email: testEmail, userId }
    );

    // Navigate to company info page
    await page.goto('http://localhost:9000/en/signup/company-info');

    // Fill form
    await page.fill('input[id="companyName"]', testData.companyName);
    await page.selectOption('select[id="industry"]', 'education');
    await page.selectOption('select[id="companySize"]', '11-50');
    await page.selectOption('select[id="gccCountry"]', 'uae');
    await page.fill('input[id="phoneNumber"]', testData.phoneNumber);
    await page.fill('input[id="agentCount"]', '3-5');

    // Select at least one service
    await page.click('label:has-text("Booking Automation")');

    // Submit
    await page.click('button[type="submit"]:has-text("Continue")');

    // Wait for success
    await page.waitForURL(/.*\/signup\/onboarding/, { timeout: 10000 });

    // Verify Prisma save
    const prismaUser = await prisma.users.findUnique({
      where: { email: testEmail },
    });

    expect(prismaUser).toBeDefined();
    expect(prismaUser!.companyName).toBe(testData.companyName);
    expect(prismaUser!.industry).toBe('education');
    expect(prismaUser!.companySize).toBe('11-50');

    // Verify Supabase save (if Supabase is running)
  });

  /**
   * BUG PREVENTION #8: Audit Trail Validation
   *
   * Ensures audit logs are created with proper IDs
   */
  test('should create audit log with valid UUID', async ({ page }) => {
    // Create test user
    const userId = generateUUID();
    await prisma.users.create({
      data: {
        id: userId,
        email: testEmail,
        name: testData.fullName,
        emailVerified: new Date(),
        createdAt: new Date(),
        updatedAt: new Date(),
      },
    });

    await page.evaluate(
      ({ email, userId }) => {
        localStorage.setItem(
          'signupData',
          JSON.stringify({
            email,
            userId,
            fullName: 'Test User',
            plan: { tierId: 'tier2' },
            verified: true,
          })
        );
      },
      { email: testEmail, userId }
    );

    await page.goto('http://localhost:9000/en/signup/company-info');

    // Fill minimal required fields
    await page.fill('input[id="companyName"]', testData.companyName);
    await page.selectOption('select[id="industry"]', 'education');
    await page.selectOption('select[id="companySize"]', '11-50');
    await page.selectOption('select[id="gccCountry"]', 'uae');
    await page.fill('input[id="phoneNumber"]', testData.phoneNumber);
    await page.fill('input[id="agentCount"]', '3-5');

    await page.click('button[type="submit"]:has-text("Continue")');

    await page.waitForURL(/.*\/signup\/onboarding/, { timeout: 10000 });

    // Verify audit log was created with UUID
    const auditLog = await prisma.audit_logs.findFirst({
      where: {
        userId,
        type: 'company_info_update',
      },
      orderBy: { createdAt: 'desc' },
    });

    expect(auditLog).toBeDefined();
    expect(auditLog!.id).toBeDefined();
    expect(auditLog!.id).toMatch(
      /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
    );
    expect(auditLog!.success).toBe(true);
    expect(auditLog!.action).toBe('User updated company information');
  });

  /**
   * BUG PREVENTION #9: Error Message Display
   *
   * Ensures errors are shown to users in UI
   */
  test('should display API errors in the UI', async ({ page }) => {
    await page.goto('http://localhost:9000/en/signup/company-info');

    // Intercept API and return validation error
    await page.route('**/api/onboarding/company-info', async (route) => {
      await route.fulfill({
        status: 400,
        contentType: 'application/json',
        body: JSON.stringify({
          error: 'Invalid data',
          details: [
            { field: 'companyName', message: 'String must contain at least 2 character(s)' },
            { field: 'industry', message: 'Required' },
          ],
        }),
      });
    });

    // Set fake signup data
    await page.evaluate(() => {
      localStorage.setItem(
        'signupData',
        JSON.stringify({
          email: 'test@example.com',
          userId: 'user-123',
          verified: true,
        })
      );
    });

    // Fill and submit
    await page.fill('input[id="companyName"]', 'A'); // Too short
    await page.click('button[type="submit"]:has-text("Continue")');

    // Should show validation error in UI
    await expect(
      page.locator('text=Validation failed: companyName')
    ).toBeVisible({ timeout: 3000 });
  });

  /**
   * BUG PREVENTION #10: Skip Functionality
   *
   * Tests that users can skip company info
   */
  test('should allow skipping company info step', async ({ page }) => {
    const userId = generateUUID();
    await prisma.users.create({
      data: {
        id: userId,
        email: testEmail,
        name: testData.fullName,
        emailVerified: new Date(),
        createdAt: new Date(),
        updatedAt: new Date(),
      },
    });

    await page.evaluate(
      ({ email, userId }) => {
        localStorage.setItem(
          'signupData',
          JSON.stringify({
            email,
            userId,
            fullName: 'Test User',
            plan: { tierId: 'tier2' },
            verified: true,
          })
        );
      },
      { email: testEmail, userId }
    );

    await page.goto('http://localhost:9000/en/signup/company-info');

    // Click skip button
    await page.click('button:has-text("Skip")');

    // Should redirect to onboarding page
    await page.waitForURL(/.*\/signup\/onboarding/, { timeout: 5000 });

    // User should still exist but without company info
    const user = await prisma.users.findUnique({
      where: { email: testEmail },
    });

    expect(user).toBeDefined();
    expect(user!.companyName).toBeNull();
  });
});
