-- Migration: Fix infinite recursion in RLS policies
-- Problem: Self-referencing policies and circular dependencies between
-- projects <-> project_collaborators cause infinite recursion.
-- Solution: Use SECURITY DEFINER functions to bypass RLS for permission checks.

-- =============================================================================
-- HELPER FUNCTIONS (SECURITY DEFINER bypasses RLS)
-- =============================================================================

-- Check if the current user is an admin
CREATE OR REPLACE FUNCTION is_admin()
RETURNS boolean
LANGUAGE sql
SECURITY DEFINER
STABLE
AS $$
  SELECT EXISTS (
    SELECT 1 FROM profiles
    WHERE id = auth.uid()
    AND is_admin = true
  );
$$;

-- Check if the current user is the owner of a project
CREATE OR REPLACE FUNCTION is_project_owner(p_project_id uuid)
RETURNS boolean
LANGUAGE sql
SECURITY DEFINER
STABLE
AS $$
  SELECT EXISTS (
    SELECT 1 FROM projects
    WHERE id = p_project_id
    AND user_id = auth.uid()
  );
$$;

-- Check if the current user is a collaborator on a project (any role)
CREATE OR REPLACE FUNCTION is_project_collaborator(p_project_id uuid)
RETURNS boolean
LANGUAGE sql
SECURITY DEFINER
STABLE
AS $$
  SELECT EXISTS (
    SELECT 1 FROM project_collaborators
    WHERE project_id = p_project_id
    AND user_id = auth.uid()
  );
$$;

-- Check if the current user is an editor or owner collaborator on a project
CREATE OR REPLACE FUNCTION is_project_editor(p_project_id uuid)
RETURNS boolean
LANGUAGE sql
SECURITY DEFINER
STABLE
AS $$
  SELECT EXISTS (
    SELECT 1 FROM project_collaborators
    WHERE project_id = p_project_id
    AND user_id = auth.uid()
    AND role IN ('owner', 'editor')
  );
$$;

-- =============================================================================
-- FIX PROFILES POLICIES
-- =============================================================================

-- Drop the problematic admin policy (self-references profiles table)
DROP POLICY IF EXISTS "Admins can view all profiles" ON profiles;

-- Recreate using the helper function
CREATE POLICY "Admins can view all profiles"
  ON profiles
  FOR SELECT
  USING (is_admin());

-- =============================================================================
-- FIX PROJECT_COLLABORATORS POLICIES
-- =============================================================================

-- Drop the problematic SELECT policy (self-references project_collaborators)
DROP POLICY IF EXISTS "Users can view collaborators for their projects" ON project_collaborators;

-- Recreate without self-reference: user is either the collaborator row's user,
-- the project owner, or already a collaborator on that project
CREATE POLICY "Users can view collaborators for their projects"
  ON project_collaborators
  FOR SELECT
  USING (
    auth.uid() = user_id
    OR is_project_owner(project_id)
    OR is_project_collaborator(project_id)
  );

-- Drop and recreate INSERT/UPDATE/DELETE policies to use helper functions
DROP POLICY IF EXISTS "Owners can add collaborators" ON project_collaborators;
CREATE POLICY "Owners can add collaborators"
  ON project_collaborators
  FOR INSERT
  WITH CHECK (is_project_owner(project_id));

DROP POLICY IF EXISTS "Owners can update collaborators" ON project_collaborators;
CREATE POLICY "Owners can update collaborators"
  ON project_collaborators
  FOR UPDATE
  USING (is_project_owner(project_id))
  WITH CHECK (is_project_owner(project_id));

DROP POLICY IF EXISTS "Owners can remove collaborators" ON project_collaborators;
CREATE POLICY "Owners can remove collaborators"
  ON project_collaborators
  FOR DELETE
  USING (is_project_owner(project_id));

-- =============================================================================
-- FIX COLLABORATION_SESSIONS POLICIES
-- =============================================================================

-- Drop the SELECT policy that cross-references both projects and project_collaborators
DROP POLICY IF EXISTS "Collaborators can view sessions" ON collaboration_sessions;

CREATE POLICY "Collaborators can view sessions"
  ON collaboration_sessions
  FOR SELECT
  USING (
    is_project_owner(project_id)
    OR is_project_collaborator(project_id)
  );

-- =============================================================================
-- FIX AUDIT_TRAIL POLICIES
-- =============================================================================

DROP POLICY IF EXISTS "Collaborators can view audit trail" ON audit_trail;
CREATE POLICY "Collaborators can view audit trail"
  ON audit_trail
  FOR SELECT
  USING (
    is_project_owner(project_id)
    OR is_project_collaborator(project_id)
  );

DROP POLICY IF EXISTS "Collaborators can write audit entries" ON audit_trail;
CREATE POLICY "Collaborators can write audit entries"
  ON audit_trail
  FOR INSERT
  WITH CHECK (
    auth.uid() = user_id
    AND (
      is_project_owner(project_id)
      OR is_project_editor(project_id)
    )
  );

-- =============================================================================
-- FIX PROJECTS POLICIES (collaborator access)
-- =============================================================================

-- Drop the policies that query project_collaborators (creating circular deps)
DROP POLICY IF EXISTS "Collaborators can view shared projects" ON projects;
CREATE POLICY "Collaborators can view shared projects"
  ON projects
  FOR SELECT
  USING (is_project_collaborator(id));

DROP POLICY IF EXISTS "Collaborators can update shared projects" ON projects;
CREATE POLICY "Collaborators can update shared projects"
  ON projects
  FOR UPDATE
  USING (is_project_editor(id))
  WITH CHECK (is_project_editor(id));
