/**
 * Moderation Lock Management Integration Tests
 * 
 * Tests for submission locking, claiming, extending, and release mechanisms
 */

import { supabase } from '@/integrations/supabase/client';
import type { TestSuite, TestResult } from '../testRunner';

export const moderationLockTestSuite: TestSuite = {
  id: 'moderation-locks',
  name: 'Moderation Lock Management',
  description: 'Tests for submission locking, claiming, and release mechanisms',
  tests: [
    {
      id: 'lock-001',
      name: 'Claim Submission Creates Active Lock',
      description: 'Verifies that claiming a submission creates a lock with correct expiry',
      run: async (): Promise<TestResult> => {
        const startTime = Date.now();
        
        try {
          const { data: userData } = await supabase.auth.getUser();
          if (!userData.user) throw new Error('No authenticated user');
          
          // 1. Create test submission
          const { data: submission, error: createError } = await supabase
            .from('content_submissions')
            .insert({
              user_id: userData.user.id,
              submission_type: 'park',
              status: 'pending',
              content: { test: true }
            })
            .select()
            .single();
          
          if (createError) throw createError;
          
          // 2. Claim the submission (manual update for testing)
          const { error: lockError } = await supabase
            .from('content_submissions')
            .update({
              assigned_to: userData.user.id,
              locked_until: new Date(Date.now() + 15 * 60 * 1000).toISOString()
            })
            .eq('id', submission.id);
          
          if (lockError) throw new Error(`Claim failed: ${lockError.message}`);
          
          // 3. Verify lock exists
          const { data: lockedSubmission, error: fetchError } = await supabase
            .from('content_submissions')
            .select('assigned_to, locked_until')
            .eq('id', submission.id)
            .single();
          
          if (fetchError) throw fetchError;
          
          // 4. Assertions
          if (lockedSubmission.assigned_to !== userData.user.id) {
            throw new Error('Submission not assigned to current user');
          }
          
          if (!lockedSubmission.locked_until) {
            throw new Error('locked_until not set');
          }
          
          const lockedUntil = new Date(lockedSubmission.locked_until);
          const now = new Date();
          const diffMinutes = (lockedUntil.getTime() - now.getTime()) / (1000 * 60);
          
          if (diffMinutes < 14 || diffMinutes > 16) {
            throw new Error(`Lock duration incorrect: ${diffMinutes} minutes`);
          }
          
          // Cleanup
          await supabase.from('content_submissions').delete().eq('id', submission.id);
          
          return {
            id: 'lock-001',
            name: 'Claim Submission Creates Active Lock',
            suite: 'Moderation Lock Management',
            status: 'pass',
            duration: Date.now() - startTime,
            timestamp: new Date().toISOString(),
            details: {
              submissionId: submission.id,
              lockDurationMinutes: diffMinutes,
              assignedTo: lockedSubmission.assigned_to
            }
          };
        } catch (error) {
          return {
            id: 'lock-001',
            name: 'Claim Submission Creates Active Lock',
            suite: 'Moderation Lock Management',
            status: 'fail',
            duration: Date.now() - startTime,
            error: error instanceof Error ? error.message : String(error),
            timestamp: new Date().toISOString()
          };
        }
      }
    },
    
    {
      id: 'lock-002',
      name: 'Release Lock Clears Assignment',
      description: 'Verifies that releasing a lock clears assigned_to and locked_until',
      run: async (): Promise<TestResult> => {
        const startTime = Date.now();
        
        try {
          const { data: userData } = await supabase.auth.getUser();
          if (!userData.user) throw new Error('No authenticated user');
          
          // Create and claim submission
          const { data: submission, error: createError } = await supabase
            .from('content_submissions')
            .insert({
              user_id: userData.user.id,
              submission_type: 'park',
              status: 'pending',
              content: { test: true }
            })
            .select()
            .single();
          
          if (createError) throw createError;
          
          await supabase
            .from('content_submissions')
            .update({
              assigned_to: userData.user.id,
              locked_until: new Date(Date.now() + 15 * 60 * 1000).toISOString()
            })
            .eq('id', submission.id);
          
          // Release lock
          const { error: releaseError } = await supabase
            .from('content_submissions')
            .update({
              assigned_to: null,
              locked_until: null
            })
            .eq('id', submission.id);
          
          if (releaseError) throw new Error(`release_lock failed: ${releaseError.message}`);
          
          // Verify lock cleared
          const { data: releasedSubmission, error: fetchError } = await supabase
            .from('content_submissions')
            .select('assigned_to, locked_until')
            .eq('id', submission.id)
            .single();
          
          if (fetchError) throw fetchError;
          
          if (releasedSubmission.assigned_to !== null) {
            throw new Error('assigned_to not cleared');
          }
          
          if (releasedSubmission.locked_until !== null) {
            throw new Error('locked_until not cleared');
          }
          
          // Cleanup
          await supabase.from('content_submissions').delete().eq('id', submission.id);
          
          return {
            id: 'lock-002',
            name: 'Release Lock Clears Assignment',
            suite: 'Moderation Lock Management',
            status: 'pass',
            duration: Date.now() - startTime,
            timestamp: new Date().toISOString()
          };
        } catch (error) {
          return {
            id: 'lock-002',
            name: 'Release Lock Clears Assignment',
            suite: 'Moderation Lock Management',
            status: 'fail',
            duration: Date.now() - startTime,
            error: error instanceof Error ? error.message : String(error),
            timestamp: new Date().toISOString()
          };
        }
      }
    },
    
    {
      id: 'lock-003',
      name: 'Extend Lock Adds 15 Minutes',
      description: 'Verifies that extending a lock adds correct duration',
      run: async (): Promise<TestResult> => {
        const startTime = Date.now();
        
        try {
          const { data: userData } = await supabase.auth.getUser();
          if (!userData.user) throw new Error('No authenticated user');
          
          // Create and claim submission
          const { data: submission, error: createError } = await supabase
            .from('content_submissions')
            .insert({
              user_id: userData.user.id,
              submission_type: 'park',
              status: 'pending',
              content: { test: true }
            })
            .select()
            .single();
          
          if (createError) throw createError;
          
          const initialLockTime = new Date(Date.now() + 15 * 60 * 1000);
          await supabase
            .from('content_submissions')
            .update({
              assigned_to: userData.user.id,
              locked_until: initialLockTime.toISOString()
            })
            .eq('id', submission.id);
          
          // Get initial lock time
          const { data: initialLock } = await supabase
            .from('content_submissions')
            .select('locked_until')
            .eq('id', submission.id)
            .single();
          
          // Extend lock (add 15 more minutes)
          const extendedLockTime = new Date(initialLockTime.getTime() + 15 * 60 * 1000);
          const { error: extendError } = await supabase
            .from('content_submissions')
            .update({
              locked_until: extendedLockTime.toISOString()
            })
            .eq('id', submission.id);
          
          if (extendError) throw new Error(`extend_lock failed: ${extendError.message}`);
          
          // Verify extended lock
          const { data: extendedLock, error: fetchError } = await supabase
            .from('content_submissions')
            .select('locked_until')
            .eq('id', submission.id)
            .single();
          
          if (fetchError) throw fetchError;
          
          if (!initialLock?.locked_until || !extendedLock.locked_until) {
            throw new Error('Lock times not found');
          }
          
          const initialTime = new Date(initialLock.locked_until);
          const extendedTime = new Date(extendedLock.locked_until);
          const diffMinutes = (extendedTime.getTime() - initialTime.getTime()) / (1000 * 60);
          
          if (diffMinutes < 14 || diffMinutes > 16) {
            throw new Error(`Extension duration incorrect: ${diffMinutes} minutes`);
          }
          
          // Cleanup
          await supabase.from('content_submissions').delete().eq('id', submission.id);
          
          return {
            id: 'lock-003',
            name: 'Extend Lock Adds 15 Minutes',
            suite: 'Moderation Lock Management',
            status: 'pass',
            duration: Date.now() - startTime,
            timestamp: new Date().toISOString(),
            details: {
              extensionMinutes: diffMinutes
            }
          };
        } catch (error) {
          return {
            id: 'lock-003',
            name: 'Extend Lock Adds 15 Minutes',
            suite: 'Moderation Lock Management',
            status: 'fail',
            duration: Date.now() - startTime,
            error: error instanceof Error ? error.message : String(error),
            timestamp: new Date().toISOString()
          };
        }
      }
    }
  ]
};
