begin;
select plan(36); -- Total number of tests (reduced - removed 2 DELETE policy tests that don't exist)

-- ============================================================================
-- RLS Enabled Tests
-- ============================================================================

SELECT is(
    (SELECT relrowsecurity FROM pg_class WHERE relname = 'notes' AND relnamespace = 'public'::regnamespace),
    true,
    'RLS should be enabled on notes table'
);

SELECT is(
    (SELECT relrowsecurity FROM pg_class WHERE relname = 'shared_notes' AND relnamespace = 'public'::regnamespace),
    true,
    'RLS should be enabled on shared_notes table'
);

SELECT is(
    (SELECT relrowsecurity FROM pg_class WHERE relname = 'note_access' AND relnamespace = 'public'::regnamespace),
    true,
    'RLS should be enabled on note_access table'
);

-- ============================================================================
-- Notes Table RLS Policies
-- ============================================================================

SELECT ok(
    (SELECT COUNT(*) FROM pg_policies WHERE tablename = 'notes' AND policyname = 'Users can view their own notes and public notes') > 0,
    'Policy for viewing own and public notes should exist'
);

SELECT ok(
    (SELECT COUNT(*) FROM pg_policies WHERE tablename = 'notes' AND policyname = 'Users can insert their own notes') > 0,
    'Policy for inserting own notes should exist'
);

SELECT ok(
    (SELECT COUNT(*) FROM pg_policies WHERE tablename = 'notes' AND policyname = 'Users can update their own notes') > 0,
    'Policy for updating own notes should exist'
);

-- Note: There is only a soft delete policy (FOR UPDATE), no hard DELETE policy
SELECT ok(
    (SELECT COUNT(*) FROM pg_policies WHERE tablename = 'notes' AND policyname = 'Users can delete their own notes (soft)') > 0,
    'Policy for soft deleting own notes should exist'
);

-- Test policy commands
SELECT is(
    (SELECT cmd FROM pg_policies WHERE tablename = 'notes' AND policyname = 'Users can view their own notes and public notes' LIMIT 1),
    'SELECT',
    'View notes policy should be for SELECT'
);

SELECT is(
    (SELECT cmd FROM pg_policies WHERE tablename = 'notes' AND policyname = 'Users can insert their own notes' LIMIT 1),
    'INSERT',
    'Insert notes policy should be for INSERT'
);

SELECT is(
    (SELECT cmd FROM pg_policies WHERE tablename = 'notes' AND policyname = 'Users can update their own notes' LIMIT 1),
    'UPDATE',
    'Update notes policy should be for UPDATE'
);

-- Note: Soft delete policy is FOR UPDATE, not DELETE
SELECT is(
    (SELECT cmd FROM pg_policies WHERE tablename = 'notes' AND policyname = 'Users can delete their own notes (soft)' LIMIT 1),
    'UPDATE',
    'Soft delete notes policy should be for UPDATE'
);

-- Test policy roles include both authenticated and anon for viewing
SELECT ok(
    (SELECT COALESCE('authenticated' = ANY(roles), false) FROM pg_policies WHERE tablename = 'notes' AND policyname = 'Users can view their own notes and public notes' LIMIT 1),
    'View notes policy should include authenticated role'
);

SELECT ok(
    (SELECT COALESCE('anon' = ANY(roles), false) FROM pg_policies WHERE tablename = 'notes' AND policyname = 'Users can view their own notes and public notes' LIMIT 1),
    'View notes policy should include anon role for public notes'
);

-- ============================================================================
-- Shared Notes Table RLS Policies
-- ============================================================================

SELECT ok(
    (SELECT COUNT(*) FROM pg_policies WHERE tablename = 'shared_notes' AND policyname = 'Users can view their own shared notes') > 0,
    'Policy for viewing own shared notes should exist'
);

SELECT ok(
    (SELECT COUNT(*) FROM pg_policies WHERE tablename = 'shared_notes' AND policyname = 'Anyone can view public notes') > 0,
    'Policy for viewing public notes should exist'
);

SELECT ok(
    (SELECT COUNT(*) FROM pg_policies WHERE tablename = 'shared_notes' AND policyname = 'Users can insert their own shared notes') > 0,
    'Policy for inserting shared notes should exist'
);

SELECT ok(
    (SELECT COUNT(*) FROM pg_policies WHERE tablename = 'shared_notes' AND policyname = 'Users can update their own shared notes') > 0,
    'Policy for updating shared notes should exist'
);

SELECT ok(
    (SELECT COUNT(*) FROM pg_policies WHERE tablename = 'shared_notes' AND policyname = 'Users can delete their own shared notes') > 0,
    'Policy for deleting shared notes should exist'
);

-- Test policy commands
SELECT is(
    (SELECT cmd FROM pg_policies WHERE tablename = 'shared_notes' AND policyname = 'Users can view their own shared notes' LIMIT 1),
    'SELECT',
    'View own shared notes policy should be for SELECT'
);

SELECT is(
    (SELECT cmd FROM pg_policies WHERE tablename = 'shared_notes' AND policyname = 'Anyone can view public notes' LIMIT 1),
    'SELECT',
    'View public notes policy should be for SELECT'
);

-- Test that public notes policy applies to both authenticated and anon
SELECT ok(
    (SELECT COALESCE('authenticated' = ANY(roles), false) FROM pg_policies WHERE tablename = 'shared_notes' AND policyname = 'Anyone can view public notes' LIMIT 1),
    'Public notes policy should include authenticated role'
);

SELECT ok(
    (SELECT COALESCE('anon' = ANY(roles), false) FROM pg_policies WHERE tablename = 'shared_notes' AND policyname = 'Anyone can view public notes' LIMIT 1),
    'Public notes policy should include anon role'
);

-- ============================================================================
-- Note Access Table RLS Policies
-- ============================================================================

SELECT ok(
    (SELECT COUNT(*) FROM pg_policies WHERE tablename = 'note_access' AND policyname = 'Users can view their own note access') > 0,
    'Policy for viewing own note access should exist'
);

SELECT ok(
    (SELECT COUNT(*) FROM pg_policies WHERE tablename = 'note_access' AND policyname = 'Users can view notes shared with their tablos') > 0,
    'Policy for viewing shared notes should exist'
);

SELECT ok(
    (SELECT COUNT(*) FROM pg_policies WHERE tablename = 'note_access' AND policyname = 'Users can insert their own note access') > 0,
    'Policy for inserting note access should exist'
);

SELECT ok(
    (SELECT COUNT(*) FROM pg_policies WHERE tablename = 'note_access' AND policyname = 'Users can update their own note access') > 0,
    'Policy for updating note access should exist'
);

SELECT ok(
    (SELECT COUNT(*) FROM pg_policies WHERE tablename = 'note_access' AND policyname = 'Users can delete their own note access') > 0,
    'Policy for deleting note access should exist'
);

-- Test policy commands
SELECT is(
    (SELECT cmd FROM pg_policies WHERE tablename = 'note_access' AND policyname = 'Users can view their own note access' LIMIT 1),
    'SELECT',
    'View own note access policy should be for SELECT'
);

SELECT is(
    (SELECT cmd FROM pg_policies WHERE tablename = 'note_access' AND policyname = 'Users can insert their own note access' LIMIT 1),
    'INSERT',
    'Insert note access policy should be for INSERT'
);

-- ============================================================================
-- Notes Behavior Tests with Mock Data
-- ============================================================================

-- Create test users and notes
DO $$
DECLARE
    user1_id uuid := gen_random_uuid();
    user2_id uuid := gen_random_uuid();
    note1_id text := 'test_note_' || gen_random_uuid()::text;
    note2_id text := 'test_note_' || gen_random_uuid()::text;
    public_note_id text := 'public_note_' || gen_random_uuid()::text;
BEGIN
    -- Insert test users
    INSERT INTO auth.users (id, instance_id, aud, role, email, encrypted_password, email_confirmed_at, created_at, updated_at)
    VALUES 
        (user1_id, '00000000-0000-0000-0000-000000000000', 'authenticated', 'authenticated', 'noteuser1_' || user1_id::text || '@test.com', 'encrypted', now(), now(), now()),
        (user2_id, '00000000-0000-0000-0000-000000000000', 'authenticated', 'authenticated', 'noteuser2_' || user2_id::text || '@test.com', 'encrypted', now(), now(), now())
    ON CONFLICT DO NOTHING;
    
    -- Insert test profiles
    INSERT INTO public.profiles (id, email, first_name, last_name, short_user_id)
    VALUES 
        (user1_id, 'noteuser1_' || user1_id::text || '@test.com', 'Note User', 'One', substring(user1_id::text from 1 for 8)),
        (user2_id, 'noteuser2_' || user2_id::text || '@test.com', 'Note User', 'Two', substring(user2_id::text from 1 for 8))
    ON CONFLICT DO NOTHING;
    
    -- Insert test notes
    INSERT INTO public.notes (id, title, content, user_id)
    VALUES 
        (note1_id, 'User 1 Private Note', 'This is a private note', user1_id),
        (note2_id, 'User 2 Private Note', 'This is another private note', user2_id),
        (public_note_id, 'Public Note', 'This is a public note', user1_id);
    
    -- Make one note public
    INSERT INTO public.shared_notes (note_id, user_id, is_public)
    VALUES (public_note_id, user1_id, true);
    
    -- Store test IDs
    PERFORM set_config('test.note_user1_id', user1_id::text, true);
    PERFORM set_config('test.note_user2_id', user2_id::text, true);
    PERFORM set_config('test.note1_id', note1_id, true);
    PERFORM set_config('test.public_note_id', public_note_id, true);
END $$;

-- Test: Verify notes were created
SELECT is(
    (SELECT count(*)::integer FROM public.notes WHERE id = current_setting('test.note1_id')),
    1,
    'User 1 private note should be created'
);

SELECT is(
    (SELECT count(*)::integer FROM public.notes WHERE id = current_setting('test.public_note_id')),
    1,
    'Public note should be created'
);

-- Test: Verify shared_notes entry for public note
SELECT is(
    (SELECT is_public FROM public.shared_notes WHERE note_id = current_setting('test.public_note_id') LIMIT 1),
    true,
    'Public note should be marked as public in shared_notes'
);

-- ============================================================================
-- Foreign Key Constraints Tests
-- ============================================================================

SELECT has_fk('public', 'shared_notes', 'shared_notes should have foreign key constraints');
SELECT has_fk('public', 'note_access', 'note_access should have foreign key constraints');

-- Test that shared_notes.note_id references notes.id
SELECT fk_ok(
    'public', 'shared_notes', 'note_id',
    'public', 'notes', 'id',
    'shared_notes.note_id should reference notes.id'
);

-- Test that note_access.note_id references notes.id
SELECT fk_ok(
    'public', 'note_access', 'note_id',
    'public', 'notes', 'id',
    'note_access.note_id should reference notes.id'
);

select * from finish();
rollback;

