/**
 * Integration Tests for Moderation Security
 * 
 * Tests backend validation, lock enforcement, and audit logging
 */

import { test, expect } from '@playwright/test';
import { setupTestUser, supabaseAdmin, cleanupTestData } from '../fixtures/database';
import { createClient } from '@supabase/supabase-js';

const supabaseUrl = 'https://ydvtmnrszybqnbcqbdcy.supabase.co';
const supabaseAnonKey = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InlkdnRtbnJzenlicW5iY3FiZGN5Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTgzMjYzNTYsImV4cCI6MjA3MzkwMjM1Nn0.DM3oyapd_omP5ZzIlrT0H9qBsiQBxBRgw2tYuqgXKX4';

test.describe('Moderation Security', () => {
  test.beforeAll(async () => {
    await cleanupTestData();
  });

  test.afterAll(async () => {
    await cleanupTestData();
  });

  test('should validate moderator role before allowing actions', async () => {
    // Create a regular user (not moderator)
    const { userId, email } = await setupTestUser(
      'regular-user@test.com',
      'TestPassword123!',
      'user'
    );

    // Create authenticated client for regular user
    const userClient = createClient(supabaseUrl, supabaseAnonKey);
    await userClient.auth.signInWithPassword({
      email,
      password: 'TestPassword123!',
    });

    // Create a test submission
    if (!supabaseAdmin) {
      throw new Error('Admin client not available');
    }

    const { data: submission } = await supabaseAdmin
      .from('content_submissions')
      .insert({
        submission_type: 'review',
        status: 'pending',
        submitted_by: userId,
        is_test_data: true,
      })
      .select()
      .single();

    expect(submission).toBeTruthy();

    // Try to call validation function as regular user (should fail)
    const { data, error } = await userClient.rpc('validate_moderation_action', {
      _submission_id: submission!.id,
      _user_id: userId,
      _action: 'approve',
    });

    // Should fail with authorization error
    expect(error).toBeTruthy();
    expect(error?.message).toContain('Unauthorized');

    await userClient.auth.signOut();
  });

  test('should enforce lock when another moderator has claimed submission', async () => {
    // Create two moderators
    const { userId: mod1Id, email: mod1Email } = await setupTestUser(
      'moderator1@test.com',
      'TestPassword123!',
      'moderator'
    );

    const { userId: mod2Id, email: mod2Email } = await setupTestUser(
      'moderator2@test.com',
      'TestPassword123!',
      'moderator'
    );

    // Create submission
    if (!supabaseAdmin) {
      throw new Error('Admin client not available');
    }

    const { data: submission } = await supabaseAdmin
      .from('content_submissions')
      .insert({
        submission_type: 'review',
        status: 'pending',
        submitted_by: mod1Id,
        is_test_data: true,
      })
      .select()
      .single();

    // Moderator 1 claims the submission
    const mod1Client = createClient(supabaseUrl, supabaseAnonKey);
    await mod1Client.auth.signInWithPassword({
      email: mod1Email,
      password: 'TestPassword123!',
    });

    await mod1Client
      .from('content_submissions')
      .update({
        assigned_to: mod1Id,
        locked_until: new Date(Date.now() + 15 * 60 * 1000).toISOString(),
      })
      .eq('id', submission!.id);

    // Moderator 2 tries to validate action (should fail due to lock)
    const mod2Client = createClient(supabaseUrl, supabaseAnonKey);
    await mod2Client.auth.signInWithPassword({
      email: mod2Email,
      password: 'TestPassword123!',
    });

    const { data, error } = await mod2Client.rpc('validate_moderation_action', {
      _submission_id: submission!.id,
      _user_id: mod2Id,
      _action: 'approve',
    });

    // Should fail with lock error
    expect(error).toBeTruthy();
    expect(error?.message).toContain('locked by another moderator');

    await mod1Client.auth.signOut();
    await mod2Client.auth.signOut();
  });

  test('should create audit log entries for moderation actions', async () => {
    const { userId, email } = await setupTestUser(
      'audit-moderator@test.com',
      'TestPassword123!',
      'moderator'
    );

    if (!supabaseAdmin) {
      throw new Error('Admin client not available');
    }

    // Create submission
    const { data: submission } = await supabaseAdmin
      .from('content_submissions')
      .insert({
        submission_type: 'review',
        status: 'pending',
        submitted_by: userId,
        is_test_data: true,
      })
      .select()
      .single();

    const modClient = createClient(supabaseUrl, supabaseAnonKey);
    await modClient.auth.signInWithPassword({
      email,
      password: 'TestPassword123!',
    });

    // Claim submission (should trigger audit log)
    await modClient
      .from('content_submissions')
      .update({
        assigned_to: userId,
        locked_until: new Date(Date.now() + 15 * 60 * 1000).toISOString(),
      })
      .eq('id', submission!.id);

    // Wait a moment for trigger to fire
    await new Promise(resolve => setTimeout(resolve, 1000));

    // Check audit log
    const { data: auditLogs } = await supabaseAdmin
      .from('moderation_audit_log')
      .select('*')
      .eq('submission_id', submission!.id)
      .eq('action', 'claim');

    expect(auditLogs).toBeTruthy();
    expect(auditLogs!.length).toBeGreaterThan(0);
    expect(auditLogs![0].moderator_id).toBe(userId);

    await modClient.auth.signOut();
  });

  test('should enforce rate limiting (10 actions per minute)', async () => {
    const { userId, email } = await setupTestUser(
      'rate-limit-mod@test.com',
      'TestPassword123!',
      'moderator'
    );

    if (!supabaseAdmin) {
      throw new Error('Admin client not available');
    }

    const modClient = createClient(supabaseUrl, supabaseAnonKey);
    await modClient.auth.signInWithPassword({
      email,
      password: 'TestPassword123!',
    });

    // Create 11 submissions
    const submissions = [];
    for (let i = 0; i < 11; i++) {
      const { data } = await supabaseAdmin
        .from('content_submissions')
        .insert({
          submission_type: 'review',
          status: 'pending',
          submitted_by: userId,
          is_test_data: true,
        })
        .select()
        .single();
      submissions.push(data);
    }

    // Try to validate 11 actions (should fail on 11th)
    let successCount = 0;
    let failCount = 0;

    for (const submission of submissions) {
      const { error } = await modClient.rpc('validate_moderation_action', {
        _submission_id: submission!.id,
        _user_id: userId,
        _action: 'approve',
      });

      if (error) {
        failCount++;
        expect(error.message).toContain('Rate limit exceeded');
      } else {
        successCount++;
      }
    }

    // Should have at least one failure due to rate limiting
    expect(failCount).toBeGreaterThan(0);
    expect(successCount).toBeLessThanOrEqual(10);

    await modClient.auth.signOut();
  });
});
