-- Row-Level Security (RLS) for Multi-Tenant Isolation
-- This migration enables RLS on all tenant-scoped tables and creates policies
-- to ensure users can only access data within their authorized workspaces.

-- =============================================================================
-- ENABLE RLS ON TENANT-SCOPED TABLES
-- =============================================================================

ALTER TABLE workspaces ENABLE ROW LEVEL SECURITY;
ALTER TABLE workspace_members ENABLE ROW LEVEL SECURITY;
ALTER TABLE teams ENABLE ROW LEVEL SECURITY;
ALTER TABLE team_members ENABLE ROW LEVEL SECURITY;
ALTER TABLE tasks ENABLE ROW LEVEL SECURITY;
ALTER TABLE events ENABLE ROW LEVEL SECURITY;
ALTER TABLE projects ENABLE ROW LEVEL SECURITY;
ALTER TABLE activity_logs ENABLE ROW LEVEL SECURITY;
ALTER TABLE memory_embeddings ENABLE ROW LEVEL SECURITY;
ALTER TABLE domains ENABLE ROW LEVEL SECURITY;
ALTER TABLE ideas ENABLE ROW LEVEL SECURITY;
ALTER TABLE relationships ENABLE ROW LEVEL SECURITY;
ALTER TABLE agents ENABLE ROW LEVEL SECURITY;
ALTER TABLE agent_sessions ENABLE ROW LEVEL SECURITY;
ALTER TABLE user_layouts ENABLE ROW LEVEL SECURITY;
ALTER TABLE knowledge_entries ENABLE ROW LEVEL SECURITY;
ALTER TABLE knowledge_tags ENABLE ROW LEVEL SECURITY;
ALTER TABLE knowledge_entry_tags ENABLE ROW LEVEL SECURITY;
ALTER TABLE knowledge_links ENABLE ROW LEVEL SECURITY;
ALTER TABLE knowledge_embeddings ENABLE ROW LEVEL SECURITY;
ALTER TABLE knowledge_entry_versions ENABLE ROW LEVEL SECURITY;

-- =============================================================================
-- HELPER FUNCTION: Check if user is workspace member
-- =============================================================================

CREATE OR REPLACE FUNCTION is_workspace_member(workspace_uuid UUID, user_uuid UUID)
RETURNS BOOLEAN AS $$
BEGIN
  RETURN EXISTS (
    SELECT 1 FROM workspace_members
    WHERE workspace_id = workspace_uuid
    AND user_id = user_uuid
  );
END;
$$ LANGUAGE plpgsql STABLE SECURITY DEFINER;

-- =============================================================================
-- HELPER FUNCTION: Check if user is workspace owner/admin
-- =============================================================================

CREATE OR REPLACE FUNCTION is_workspace_admin(workspace_uuid UUID, user_uuid UUID)
RETURNS BOOLEAN AS $$
BEGIN
  RETURN EXISTS (
    SELECT 1 FROM workspace_members
    WHERE workspace_id = workspace_uuid
    AND user_id = user_uuid
    AND role IN ('OWNER', 'ADMIN')
  );
END;
$$ LANGUAGE plpgsql STABLE SECURITY DEFINER;

-- =============================================================================
-- HELPER FUNCTION: Get current user ID from session variable
-- =============================================================================
-- Usage in API: SET LOCAL app.current_user_id = 'user-uuid';

CREATE OR REPLACE FUNCTION current_user_id()
RETURNS UUID AS $$
BEGIN
  RETURN NULLIF(current_setting('app.current_user_id', TRUE), '')::UUID;
EXCEPTION
  WHEN OTHERS THEN
    RETURN NULL;
END;
$$ LANGUAGE plpgsql STABLE;

-- =============================================================================
-- WORKSPACES: Users can only see workspaces they're members of
-- =============================================================================

CREATE POLICY workspace_member_access ON workspaces
  FOR ALL
  USING (
    id IN (
      SELECT workspace_id FROM workspace_members
      WHERE user_id = current_user_id()
    )
  );

-- =============================================================================
-- WORKSPACE_MEMBERS: Users can see members of their workspaces
-- =============================================================================

CREATE POLICY workspace_members_access ON workspace_members
  FOR ALL
  USING (
    workspace_id IN (
      SELECT workspace_id FROM workspace_members
      WHERE user_id = current_user_id()
    )
  );

-- =============================================================================
-- TEAMS: Users can see teams in their workspaces
-- =============================================================================

CREATE POLICY teams_workspace_access ON teams
  FOR ALL
  USING (
    is_workspace_member(workspace_id, current_user_id())
  );

-- =============================================================================
-- TEAM_MEMBERS: Users can see team members in their workspaces
-- =============================================================================

CREATE POLICY team_members_access ON team_members
  FOR ALL
  USING (
    team_id IN (
      SELECT id FROM teams
      WHERE is_workspace_member(workspace_id, current_user_id())
    )
  );

-- =============================================================================
-- TASKS: Users can only see tasks in their workspaces
-- =============================================================================

CREATE POLICY tasks_workspace_access ON tasks
  FOR ALL
  USING (
    is_workspace_member(workspace_id, current_user_id())
  );

-- =============================================================================
-- EVENTS: Users can only see events in their workspaces
-- =============================================================================

CREATE POLICY events_workspace_access ON events
  FOR ALL
  USING (
    is_workspace_member(workspace_id, current_user_id())
  );

-- =============================================================================
-- PROJECTS: Users can only see projects in their workspaces
-- =============================================================================

CREATE POLICY projects_workspace_access ON projects
  FOR ALL
  USING (
    is_workspace_member(workspace_id, current_user_id())
  );

-- =============================================================================
-- ACTIVITY_LOGS: Users can only see activity in their workspaces
-- =============================================================================

CREATE POLICY activity_logs_workspace_access ON activity_logs
  FOR ALL
  USING (
    is_workspace_member(workspace_id, current_user_id())
  );

-- =============================================================================
-- MEMORY_EMBEDDINGS: Users can only see embeddings in their workspaces
-- =============================================================================

CREATE POLICY memory_embeddings_workspace_access ON memory_embeddings
  FOR ALL
  USING (
    is_workspace_member(workspace_id, current_user_id())
  );

-- =============================================================================
-- DOMAINS: Users can only see domains in their workspaces
-- =============================================================================

CREATE POLICY domains_workspace_access ON domains
  FOR ALL
  USING (
    is_workspace_member(workspace_id, current_user_id())
  );

-- =============================================================================
-- IDEAS: Users can only see ideas in their workspaces
-- =============================================================================

CREATE POLICY ideas_workspace_access ON ideas
  FOR ALL
  USING (
    is_workspace_member(workspace_id, current_user_id())
  );

-- =============================================================================
-- RELATIONSHIPS: Users can only see relationships in their workspaces
-- =============================================================================

CREATE POLICY relationships_workspace_access ON relationships
  FOR ALL
  USING (
    is_workspace_member(workspace_id, current_user_id())
  );

-- =============================================================================
-- AGENTS: Users can only see agents in their workspaces
-- =============================================================================

CREATE POLICY agents_workspace_access ON agents
  FOR ALL
  USING (
    is_workspace_member(workspace_id, current_user_id())
  );

-- =============================================================================
-- AGENT_SESSIONS: Users can only see agent sessions in their workspaces
-- =============================================================================

CREATE POLICY agent_sessions_workspace_access ON agent_sessions
  FOR ALL
  USING (
    is_workspace_member(workspace_id, current_user_id())
  );

-- =============================================================================
-- USER_LAYOUTS: Users can only see their own layouts in their workspaces
-- =============================================================================

CREATE POLICY user_layouts_workspace_access ON user_layouts
  FOR ALL
  USING (
    is_workspace_member(workspace_id, current_user_id())
    AND user_id = current_user_id()
  );

-- =============================================================================
-- KNOWLEDGE_ENTRIES: Users can only see entries in their workspaces
-- =============================================================================

CREATE POLICY knowledge_entries_workspace_access ON knowledge_entries
  FOR ALL
  USING (
    is_workspace_member(workspace_id, current_user_id())
  );

-- =============================================================================
-- KNOWLEDGE_TAGS: Users can only see tags in their workspaces
-- =============================================================================

CREATE POLICY knowledge_tags_workspace_access ON knowledge_tags
  FOR ALL
  USING (
    is_workspace_member(workspace_id, current_user_id())
  );

-- =============================================================================
-- KNOWLEDGE_ENTRY_TAGS: Users can see tags for entries in their workspaces
-- =============================================================================

CREATE POLICY knowledge_entry_tags_access ON knowledge_entry_tags
  FOR ALL
  USING (
    entry_id IN (
      SELECT id FROM knowledge_entries
      WHERE is_workspace_member(workspace_id, current_user_id())
    )
  );

-- =============================================================================
-- KNOWLEDGE_LINKS: Users can see links between entries in their workspaces
-- =============================================================================

CREATE POLICY knowledge_links_access ON knowledge_links
  FOR ALL
  USING (
    source_id IN (
      SELECT id FROM knowledge_entries
      WHERE is_workspace_member(workspace_id, current_user_id())
    )
  );

-- =============================================================================
-- KNOWLEDGE_EMBEDDINGS: Users can see embeddings for entries in their workspaces
-- =============================================================================

CREATE POLICY knowledge_embeddings_access ON knowledge_embeddings
  FOR ALL
  USING (
    entry_id IN (
      SELECT id FROM knowledge_entries
      WHERE is_workspace_member(workspace_id, current_user_id())
    )
  );

-- =============================================================================
-- KNOWLEDGE_ENTRY_VERSIONS: Users can see versions for entries in their workspaces
-- =============================================================================

CREATE POLICY knowledge_entry_versions_access ON knowledge_entry_versions
  FOR ALL
  USING (
    entry_id IN (
      SELECT id FROM knowledge_entries
      WHERE is_workspace_member(workspace_id, current_user_id())
    )
  );

-- =============================================================================
-- GRANT USAGE TO APPLICATION ROLE
-- =============================================================================
-- The application should connect with a role that has appropriate permissions.
-- By default, we assume the owner of the database has full access.
-- In production, create a dedicated role with limited permissions.

-- Example (uncomment and customize for production):
-- GRANT USAGE ON SCHEMA public TO mosaic_app;
-- GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO mosaic_app;
-- GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO mosaic_app;
