/**
 * Smoke Tests for Database Save Functionality
 *
 * Critical tests that MUST pass for the application to function
 * Run these tests before every deployment
 *
 * Usage: npm run test:smoke -- database-save
 */

import { test, expect } from '@playwright/test';
import { createClient } from '@supabase/supabase-js';

const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL || 'http://localhost:54321',
  process.env.SUPABASE_SERVICE_ROLE_KEY || ''
);

test.describe('Database Save Smoke Tests', () => {
  test.describe.configure({ mode: 'serial' }); // Run tests in order

  test('CRITICAL: Supabase tables exist', async () => {
    const requiredTables = [
      'users',
      'audit_logs',
      'subscriptions',
      'billing_history',
      'payments',
      'demo_bookings',
      'otps'
    ];

    for (const tableName of requiredTables) {
      const { error } = await supabase
        .from(tableName)
        .select('*')
        .limit(0);

      expect(error, `Table ${tableName} should exist`).toBeNull();
    }
  });

  test('CRITICAL: demo_bookings has auto-ID generation', async () => {
    const testEmail = `smoke-test-${Date.now()}@example.com`;

    const { data, error } = await supabase
      .from('demo_bookings')
      .insert({
        full_name: 'Smoke Test',
        email: testEmail,
        telephone: '+974-9999-9999',
        appointment_date: '2025-12-31',
        appointment_time: '10:00',
        duration: '30min',
        language: 'en',
        status: 'pending',
        webhook_status: 'pending',
      })
      .select('id')
      .single();

    expect(error, 'Should insert without ID').toBeNull();
    expect(data, 'Should return record').toBeDefined();
    expect(data!.id, 'Should have auto-generated ID').toBeDefined();
    expect(data!.id, 'ID should be CUID format').toMatch(/^c[a-z0-9]+$/);

    // Cleanup
    await supabase.from('demo_bookings').delete().eq('email', testEmail);
  });

  test('CRITICAL: Demo booking saves via API', async ({ page }) => {
    const testEmail = `api-smoke-${Date.now()}@example.com`;

    // Navigate to demo page
    await page.goto('http://localhost:9000/en/demo');

    // Quick booking flow
    await page.getByRole('button', { name: /30 minutes/i }).click();
    await page.getByRole('button', { name: 'Next' }).click();

    // Select first available date
    await page.getByRole('button', { name: /November 2025/ }).first().click();

    // Select first available time
    await page.getByRole('button', { name: /PM/ }).first().click();
    await page.getByRole('button', { name: 'Next' }).click();

    // Fill form
    await page.getByRole('textbox', { name: /Full Name/ }).fill('Smoke Test User');
    await page.getByRole('textbox', { name: /Email/ }).fill(testEmail);
    await page.getByRole('textbox', { name: /Phone/ }).fill('50123456');
    await page.getByRole('textbox', { name: /Message/ }).fill('Critical smoke test for database save');

    await page.getByRole('button', { name: 'Next' }).click();

    // Submit
    await page.getByRole('button', { name: /Confirm/ }).click();

    // Wait for success
    await page.waitForSelector('text=/confirmed|success/i', { timeout: 10000 });

    // Verify in database
    await page.waitForTimeout(2000);

    const { data, error } = await supabase
      .from('demo_bookings')
      .select('*')
      .eq('email', testEmail)
      .single();

    expect(error, 'Booking should be saved').toBeNull();
    expect(data, 'Booking should exist').toBeDefined();
    expect(data!.full_name).toBe('Smoke Test User');
    expect(data!.status).toBe('pending');

    // Cleanup
    await supabase.from('demo_bookings').delete().eq('email', testEmail);
  });

  test('CRITICAL: User registration creates OTP', async ({ page }) => {
    const testEmail = `otp-smoke-${Date.now()}@example.com`;

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

    // Select a package
    await page.getByRole('button', { name: /Starter/i }).first().click();

    // Should show registration form or next step
    await page.waitForSelector('input[type="email"], button:has-text("Continue")', { timeout: 5000 });

    // If there's a Continue button, click it
    const continueButton = await page.locator('button:has-text("Continue")').count();
    if (continueButton > 0) {
      await page.getByRole('button', { name: /Continue/ }).click();
    }

    // Wait for registration form
    await page.waitForSelector('input[type="email"]', { timeout: 5000 });

    // Fill email
    await page.locator('input[type="email"]').fill(testEmail);

    // Fill other required fields if present
    const nameField = await page.locator('input[name="fullName"], input[name="name"]').count();
    if (nameField > 0) {
      await page.locator('input[name="fullName"], input[name="name"]').fill('Smoke Test User');
    }

    const passwordField = await page.locator('input[type="password"]').count();
    if (passwordField > 0) {
      await page.locator('input[type="password"]').fill('SmokeTest123!@#');
    }

    // Submit form
    await page.getByRole('button', { name: /sign up|register|continue/i }).click();

    // Wait for OTP screen or success
    await page.waitForSelector('text=/verification|otp|code|success/i', { timeout: 10000 });

    // Verify OTP was created in database
    await page.waitForTimeout(2000);

    const { data: otpData, error: otpError } = await supabase
      .from('otps')
      .select('*')
      .eq('email', testEmail)
      .eq('purpose', 'SIGNUP')
      .order('created_at', { ascending: false })
      .limit(1)
      .single();

    expect(otpError, 'OTP should be created').toBeNull();
    expect(otpData, 'OTP should exist').toBeDefined();
    expect(otpData!.otp_code).toMatch(/^\d{6}$/); // 6-digit code

    // Cleanup
    await supabase.from('otps').delete().eq('email', testEmail);
  });

  test('CRITICAL: Supabase connection working', async () => {
    const { data, error } = await supabase
      .from('users')
      .select('count')
      .limit(1);

    expect(error, 'Supabase should be accessible').toBeNull();
  });

  test('CRITICAL: No module errors in build', async () => {
    // This test ensures @paralleldrive/cuid2 and other packages are installed
    const fs = require('fs');
    const path = require('path');

    const cuid2Path = path.join(process.cwd(), 'node_modules/@paralleldrive/cuid2');
    const exists = fs.existsSync(cuid2Path);

    expect(exists, '@paralleldrive/cuid2 should be installed').toBe(true);
  });
});

test.describe('Database Save Regression Prevention', () => {
  test('should prevent missing table deployments', async () => {
    // This test will fail if tables are missing
    const tableChecks = [
      { table: 'demo_bookings', requiredFields: ['id', 'full_name', 'email', 'appointment_date'] },
      { table: 'users', requiredFields: ['id', 'email', 'name'] },
      { table: 'audit_logs', requiredFields: ['id', 'type', 'action', 'success'] },
      { table: 'otps', requiredFields: ['id', 'email', 'otp_code', 'purpose'] },
    ];

    for (const { table, requiredFields } of tableChecks) {
      const { data, error } = await supabase
        .from(table)
        .select(requiredFields.join(','))
        .limit(1);

      expect(error, `Table ${table} with required fields should be queryable`).toBeNull();
    }
  });

  test('should prevent ID generation failures', async () => {
    // Test that demo_bookings can insert without explicit ID
    const { data, error } = await supabase
      .from('demo_bookings')
      .insert({
        full_name: 'ID Gen Test',
        email: `id-gen-test-${Date.now()}@example.com`,
        telephone: '+974-0000-0000',
        appointment_date: '2025-12-31',
        appointment_time: '23:59',
        duration: '30min',
        language: 'en',
        status: 'pending',
        webhook_status: 'pending',
      })
      .select('id')
      .single();

    expect(error, 'Should insert without ID').toBeNull();
    expect(data?.id, 'Should have ID').toBeDefined();
    expect(data?.id, 'ID should be CUID').toMatch(/^c[a-z0-9]{20,}$/);

    // Cleanup
    if (data?.id) {
      await supabase.from('demo_bookings').delete().eq('id', data.id);
    }
  });
});
