/**
 * Data Integrity & Constraints Test Suite
 * 
 * Tests database constraints, RLS policies, and data integrity rules.
 */

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

export const dataIntegrityTestSuite: TestSuite = {
  id: 'data-integrity',
  name: 'Data Integrity & Constraints',
  description: 'Tests database constraints, RLS policies, and data integrity',
  tests: [
    {
      id: 'integrity-001',
      name: 'RLS Policy Enforcement - Public Read',
      description: 'Validates public read access to entity tables',
      run: async (): Promise<TestResult> => {
        const startTime = Date.now();
        
        try {
          // Test public read access to parks
          const { data: parks, error: parksError } = await supabase
            .from('parks')
            .select('id, name, slug')
            .limit(5);
          
          if (parksError) throw new Error(`Parks read failed: ${parksError.message}`);
          
          // Test public read access to rides
          const { data: rides, error: ridesError } = await supabase
            .from('rides')
            .select('id, name, slug')
            .limit(5);
          
          if (ridesError) throw new Error(`Rides read failed: ${ridesError.message}`);
          
          // Test public read access to companies
          const { data: companies, error: companiesError } = await supabase
            .from('companies')
            .select('id, name, slug')
            .limit(5);
          
          if (companiesError) throw new Error(`Companies read failed: ${companiesError.message}`);
          
          // Test public read access to ride_models
          const { data: models, error: modelsError } = await supabase
            .from('ride_models')
            .select('id, name, slug')
            .limit(5);
          
          if (modelsError) throw new Error(`Ride models read failed: ${modelsError.message}`);
          
          const duration = Date.now() - startTime;
          
          return {
            id: 'integrity-001',
            name: 'RLS Policy Enforcement - Public Read',
            suite: 'Data Integrity & Constraints',
            status: 'pass',
            duration,
            timestamp: new Date().toISOString(),
            details: {
              parksReadable: Array.isArray(parks),
              ridesReadable: Array.isArray(rides),
              companiesReadable: Array.isArray(companies),
              rideModelsReadable: Array.isArray(models)
            }
          };
        } catch (error) {
          const duration = Date.now() - startTime;
          return {
            id: 'integrity-001',
            name: 'RLS Policy Enforcement - Public Read',
            suite: 'Data Integrity & Constraints',
            status: 'fail',
            duration,
            error: error instanceof Error ? error.message : String(error),
            stack: error instanceof Error ? error.stack : undefined,
            timestamp: new Date().toISOString()
          };
        }
      }
    },
    {
      id: 'integrity-002',
      name: 'Foreign Key Constraint Enforcement',
      description: 'Tests foreign key constraints prevent invalid references',
      run: async (): Promise<TestResult> => {
        const startTime = Date.now();
        
        try {
          // Try to create a ride with non-existent park_id
          const invalidParkId = '00000000-0000-0000-0000-000000000000';
          const slug = `test-ride-${Date.now()}`;
          
          const { error } = await supabase
            .from('rides')
            .insert({
              name: 'Invalid Ride',
              slug,
              park_id: invalidParkId,
              category: 'roller_coaster',
              status: 'operating',
              is_test_data: true
            });
          
          // This SHOULD fail with foreign key violation
          if (!error) {
            throw new Error('Foreign key constraint not enforced - invalid park_id was accepted');
          }
          
          // Verify it's a foreign key violation
          if (!error.message.includes('foreign key') && !error.message.includes('violates')) {
            throw new Error(`Expected foreign key error, got: ${error.message}`);
          }
          
          const duration = Date.now() - startTime;
          
          return {
            id: 'integrity-002',
            name: 'Foreign Key Constraint Enforcement',
            suite: 'Data Integrity & Constraints',
            status: 'pass',
            duration,
            timestamp: new Date().toISOString(),
            details: {
              constraintEnforced: true,
              errorMessage: error.message
            }
          };
        } catch (error) {
          const duration = Date.now() - startTime;
          return {
            id: 'integrity-002',
            name: 'Foreign Key Constraint Enforcement',
            suite: 'Data Integrity & Constraints',
            status: 'fail',
            duration,
            error: error instanceof Error ? error.message : String(error),
            stack: error instanceof Error ? error.stack : undefined,
            timestamp: new Date().toISOString()
          };
        }
      }
    },
    {
      id: 'integrity-003',
      name: 'Unique Constraint Enforcement',
      description: 'Tests unique constraints prevent duplicate slugs',
      run: async (): Promise<TestResult> => {
        const startTime = Date.now();
        const tracker = new TestDataTracker();
        let parkId: string | null = null;
        
        try {
          // Create a park
          const slug = `unique-test-${Date.now()}`;
          const { data: park, error: createError } = await supabase
            .from('parks')
            .insert({
              name: 'Unique Test Park',
              slug,
              park_type: 'theme_park',
              status: 'operating',
              is_test_data: true
            })
            .select('id')
            .single();
          
          if (createError) throw new Error(`Park creation failed: ${createError.message}`);
          if (!park) throw new Error('No park returned');
          
          parkId = park.id;
          tracker.track('parks', parkId);
          
          // Try to create another park with same slug
          const { error: duplicateError } = await supabase
            .from('parks')
            .insert({
              name: 'Duplicate Park',
              slug, // Same slug
              park_type: 'theme_park',
              status: 'operating',
              is_test_data: true
            });
          
          // This SHOULD fail with unique violation
          if (!duplicateError) {
            throw new Error('Unique constraint not enforced - duplicate slug was accepted');
          }
          
          // Verify it's a unique violation
          if (!duplicateError.message.includes('unique') && !duplicateError.message.includes('duplicate')) {
            throw new Error(`Expected unique constraint error, got: ${duplicateError.message}`);
          }
          
          const duration = Date.now() - startTime;
          
          return {
            id: 'integrity-003',
            name: 'Unique Constraint Enforcement',
            suite: 'Data Integrity & Constraints',
            status: 'pass',
            duration,
            timestamp: new Date().toISOString(),
            details: {
              constraintEnforced: true,
              errorMessage: duplicateError.message
            }
          };
        } catch (error) {
          const duration = Date.now() - startTime;
          return {
            id: 'integrity-003',
            name: 'Unique Constraint Enforcement',
            suite: 'Data Integrity & Constraints',
            status: 'fail',
            duration,
            error: error instanceof Error ? error.message : String(error),
            stack: error instanceof Error ? error.stack : undefined,
            timestamp: new Date().toISOString()
          };
        } finally {
          await tracker.cleanup();
          const remaining = await tracker.verifyCleanup();
          if (remaining.length > 0) {
            console.warn('integrity-003 cleanup incomplete:', remaining);
          }
        }
      }
    },
    {
      id: 'integrity-004',
      name: 'No JSONB in Entity Tables',
      description: 'Validates no JSONB columns exist in entity tables (per requirements)',
      run: async (): Promise<TestResult> => {
        const startTime = Date.now();
        
        try {
          // Sample actual data and check structure (information_schema not accessible via RLS)
          const { data: parks } = await supabase.from('parks').select('*').limit(1);
          const { data: rides } = await supabase.from('rides').select('*').limit(1);
          const { data: companies } = await supabase.from('companies').select('*').limit(1);
          const { data: models } = await supabase.from('ride_models').select('*').limit(1);
          
          // Check if any fields appear to be JSONB objects
          const hasJsonbFields = [parks, rides, companies, models].some(dataset => {
            if (!dataset || dataset.length === 0) return false;
            const record = dataset[0] as any;
            return Object.keys(record).some(key => {
              const val = record[key];
              // Check if value is a plain object (not Date, not Array, not null)
              if (val === null || val === undefined) return false;
              if (typeof val !== 'object') return false;
              if (Array.isArray(val)) return false;
              // Check if it's a Date by checking if it has getTime method
              if (val && typeof val.getTime === 'function') return false;
              // If we get here, it's likely a JSONB object
              return true;
            });
          });
          
          if (hasJsonbFields) {
            throw new Error('Found JSONB-like fields in entity tables');
          }
          
          const duration = Date.now() - startTime;
          
          return {
            id: 'integrity-004',
            name: 'No JSONB in Entity Tables',
            suite: 'Data Integrity & Constraints',
            status: 'pass',
            duration,
            timestamp: new Date().toISOString(),
            details: {
              noJsonbColumns: true,
              validation: 'Entity tables use relational structure only'
            }
          };
        } catch (error) {
          const duration = Date.now() - startTime;
          return {
            id: 'integrity-004',
            name: 'No JSONB in Entity Tables',
            suite: 'Data Integrity & Constraints',
            status: 'fail',
            duration,
            error: error instanceof Error ? error.message : String(error),
            stack: error instanceof Error ? error.stack : undefined,
            timestamp: new Date().toISOString()
          };
        }
      }
    }
  ]
};
