-- ============================================
-- FIX SERVICE ROLE RLS BYPASS
-- Ensure service_role can properly bypass RLS for storage operations
-- ============================================

-- The service_role should have BYPASSRLS attribute in Supabase
-- But in self-hosted setups, this might not be configured correctly
-- This migration ensures proper access through multiple approaches

-- Approach 1: Grant service_role BYPASSRLS (if not already set)
-- Note: This requires superuser privileges, which the migration might not have
-- If this fails, the explicit policies below will still work
DO $$
BEGIN
  -- Check if service_role exists and doesn't have bypassrls
  IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'service_role' AND NOT rolbypassrls) THEN
    ALTER ROLE service_role BYPASSRLS;
    RAISE NOTICE 'Granted BYPASSRLS to service_role';
  ELSE
    RAISE NOTICE 'service_role already has BYPASSRLS or does not exist';
  END IF;
EXCEPTION
  WHEN insufficient_privilege THEN
    RAISE NOTICE 'Could not grant BYPASSRLS (insufficient privileges) - using explicit policies instead';
  WHEN OTHERS THEN
    RAISE NOTICE 'Error granting BYPASSRLS: % - using explicit policies instead', SQLERRM;
END $$;

-- Approach 2: Ensure RLS is properly configured on storage.objects
-- Check if RLS is enabled and ensure our policies exist
DO $$
BEGIN
  -- Ensure RLS is enabled on storage.objects (it should be by default)
  IF NOT EXISTS (
    SELECT 1 FROM pg_tables
    WHERE schemaname = 'storage' AND tablename = 'objects' AND rowsecurity = true
  ) THEN
    ALTER TABLE storage.objects ENABLE ROW LEVEL SECURITY;
    RAISE NOTICE 'Enabled RLS on storage.objects';
  END IF;
END $$;

-- Approach 3: Create permissive policies for service_role on ALL storage buckets
-- These use a single policy per operation type that covers all buckets

-- First, clean up any existing service_role policies
DROP POLICY IF EXISTS "service_role_all_select" ON storage.objects;
DROP POLICY IF EXISTS "service_role_all_insert" ON storage.objects;
DROP POLICY IF EXISTS "service_role_all_update" ON storage.objects;
DROP POLICY IF EXISTS "service_role_all_delete" ON storage.objects;

-- Create universal service_role policies (allow access to ALL buckets)
CREATE POLICY "service_role_all_select" ON storage.objects
FOR SELECT TO service_role
USING (true);

CREATE POLICY "service_role_all_insert" ON storage.objects
FOR INSERT TO service_role
WITH CHECK (true);

CREATE POLICY "service_role_all_update" ON storage.objects
FOR UPDATE TO service_role
USING (true);

CREATE POLICY "service_role_all_delete" ON storage.objects
FOR DELETE TO service_role
USING (true);

-- Approach 4: Grant necessary table permissions to service_role
GRANT ALL ON storage.objects TO service_role;
GRANT ALL ON storage.buckets TO service_role;
GRANT USAGE ON SCHEMA storage TO service_role;

-- Also ensure service_role can use sequences in storage schema
DO $$
DECLARE
  seq_name text;
BEGIN
  FOR seq_name IN
    SELECT sequence_name FROM information_schema.sequences WHERE sequence_schema = 'storage'
  LOOP
    EXECUTE format('GRANT USAGE, SELECT ON SEQUENCE storage.%I TO service_role', seq_name);
  END LOOP;
END $$;

-- Verify the setup
DO $$
DECLARE
  policy_count int;
BEGIN
  SELECT COUNT(*) INTO policy_count
  FROM pg_policies
  WHERE schemaname = 'storage'
    AND tablename = 'objects'
    AND roles @> ARRAY['service_role']::name[];

  RAISE NOTICE 'service_role has % policies on storage.objects', policy_count;
END $$;
