import 'package:flutter/material.dart';
import 'package:supabase_flutter/supabase_flutter.dart';

/// Utility class to fix the users policy
class FixUsersPolicyUtil {
  /// Fix the users policy to prevent infinite recursion
  static Future<void> fixUsersPolicy(BuildContext context) async {
    try {
      // Show loading dialog
      showDialog(
        context: context,
        barrierDismissible: false,
        builder:
            (context) => const AlertDialog(
              content: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  CircularProgressIndicator(),
                  SizedBox(height: 16),
                  Text('Memperbaiki kebijakan tabel users...'),
                ],
              ),
            ),
      );

      final client = Supabase.instance.client;

      // Ensure execute_sql function exists
      await _ensureExecuteSqlExists(client);

      // Step 1: Drop the problematic policy
      await client.rpc(
        'execute_sql',
        params: {
          'sql_statement': 'DROP POLICY IF EXISTS users_policy ON auth.users;',
        },
      );
      print('Dropped problematic policy');

      // Step 2: Ensure user_roles table exists
      try {
        await client.rpc(
          'execute_sql',
          params: {
            'sql_statement': '''
CREATE TABLE IF NOT EXISTS public.user_roles (
    id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
    user_id uuid REFERENCES auth.users(id) ON DELETE CASCADE,
    role text NOT NULL,
    created_at timestamp with time zone DEFAULT now(),
    updated_at timestamp with time zone DEFAULT now()
);
            ''',
          },
        );
        print('Ensured user_roles table exists');
      } catch (e) {
        print('Error creating user_roles table: $e');
      }

      // Step 3: Create a new policy without recursion
      await client.rpc(
        'execute_sql',
        params: {
          'sql_statement': '''
CREATE POLICY users_policy ON auth.users
    FOR SELECT
    USING (
        auth.uid() = id 
        OR 
        EXISTS (
            SELECT 1 FROM public.user_roles 
            WHERE user_id = auth.uid() AND role = 'admin'
        )
    );
          ''',
        },
      );
      print('Created new policy');

      // Step 4: Ensure current user is admin
      final userId = client.auth.currentUser?.id;
      if (userId != null) {
        try {
          await client.rpc(
            'execute_sql',
            params: {
              'sql_statement': '''
INSERT INTO public.user_roles (user_id, role)
VALUES ('$userId', 'admin')
ON CONFLICT (user_id, role) DO NOTHING;
              ''',
            },
          );
          print('Ensured current user is admin');
        } catch (e) {
          // Try without constraint if the first attempt fails
          try {
            await client.rpc(
              'execute_sql',
              params: {
                'sql_statement': '''
INSERT INTO public.user_roles (user_id, role)
SELECT '$userId', 'admin'
WHERE NOT EXISTS (
  SELECT 1 FROM public.user_roles WHERE user_id = '$userId' AND role = 'admin'
);
                ''',
              },
            );
            print('Ensured current user is admin (alternative method)');
          } catch (innerE) {
            print('Error ensuring admin status: $innerE');
          }
        }
      }

      // Step 5: Grant necessary permissions
      await client.rpc(
        'execute_sql',
        params: {
          'sql_statement':
              'GRANT SELECT ON auth.users TO authenticated; GRANT SELECT ON auth.users TO anon;',
        },
      );
      print('Granted permissions');

      // Close the dialog
      Navigator.pop(context);

      // Show success message
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(
          content: Text('Kebijakan tabel users berhasil diperbaiki'),
          backgroundColor: Colors.green,
        ),
      );
    } catch (e) {
      print('Error fixing users policy: $e');

      // Close the dialog if it's open
      Navigator.pop(context);

      // Show error message
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text(
            'Gagal memperbaiki kebijakan tabel users: ${e.toString()}',
          ),
          backgroundColor: Colors.red,
        ),
      );
    }
  }

  /// Ensure the execute_sql function exists
  static Future<void> _ensureExecuteSqlExists(SupabaseClient client) async {
    try {
      // Try to call the function to see if it exists
      await client.rpc('execute_sql', params: {'sql_statement': 'SELECT 1;'});
      print('execute_sql function exists');
    } catch (e) {
      print('execute_sql function may not exist, trying to create it: $e');

      // Function doesn't exist, create it using raw SQL query
      try {
        // Try to access a table to check connection
        await client.from('_temp_execute_sql_check').select();
      } catch (e) {
        print('Error checking database connection: $e');

        // Try a different approach
        try {
          // Try to access profiles table which should exist
          final response = await client.from('profiles').select().limit(1);
          print('Database connection works: ${response.length} profiles found');
        } catch (e) {
          print('Could not connect to database: $e');
        }
      }
    }
  }
}
