-- =====================================================
-- Audit Timeline RPCs for Courses, Events, Bookings
--
-- Paginated, filterable read layer on the audit logs.
-- Mirrors get_member_timeline from 20260416000007.
-- =====================================================

-- -------------------------------------------------------
-- 1. Course timeline RPC
-- -------------------------------------------------------

CREATE OR REPLACE FUNCTION public.get_course_timeline(
  p_course_id uuid,
  p_page integer DEFAULT 1,
  p_page_size integer DEFAULT 50,
  p_action_filter text DEFAULT NULL
)
RETURNS TABLE (
  id bigint,
  action text,
  changes jsonb,
  metadata jsonb,
  user_id uuid,
  user_email text,
  created_at timestamptz,
  total_count bigint
)
LANGUAGE plpgsql
STABLE
SECURITY DEFINER
SET search_path = ''
AS $$
DECLARE
  v_account_id uuid;
  v_total bigint;
  v_offset integer;
BEGIN
  -- Get course's account for access check
  SELECT c.account_id INTO v_account_id
  FROM public.courses c WHERE c.id = p_course_id;

  IF v_account_id IS NULL THEN
    RAISE EXCEPTION 'Course not found';
  END IF;

  IF NOT public.has_role_on_account(v_account_id) THEN
    RAISE EXCEPTION 'Access denied' USING ERRCODE = '42501';
  END IF;

  -- Clamp page size to prevent unbounded queries
  p_page_size := LEAST(GREATEST(p_page_size, 1), 200);
  v_offset := GREATEST(0, (p_page - 1)) * p_page_size;

  -- Get total count
  SELECT count(*) INTO v_total
  FROM public.course_audit_log cal
  WHERE cal.course_id = p_course_id
    AND (p_action_filter IS NULL OR cal.action = p_action_filter);

  -- Return paginated results with user email
  RETURN QUERY
  SELECT
    cal.id,
    cal.action,
    cal.changes,
    cal.metadata,
    cal.user_id,
    u.email::text AS user_email,
    cal.created_at,
    v_total AS total_count
  FROM public.course_audit_log cal
  LEFT JOIN auth.users u ON u.id = cal.user_id
  WHERE cal.course_id = p_course_id
    AND (p_action_filter IS NULL OR cal.action = p_action_filter)
  ORDER BY cal.created_at DESC
  LIMIT p_page_size OFFSET v_offset;
END;
$$;

GRANT EXECUTE ON FUNCTION public.get_course_timeline(uuid, integer, integer, text)
  TO authenticated, service_role;

-- -------------------------------------------------------
-- 2. Event timeline RPC
-- -------------------------------------------------------

CREATE OR REPLACE FUNCTION public.get_event_timeline(
  p_event_id uuid,
  p_page integer DEFAULT 1,
  p_page_size integer DEFAULT 50,
  p_action_filter text DEFAULT NULL
)
RETURNS TABLE (
  id bigint,
  action text,
  changes jsonb,
  metadata jsonb,
  user_id uuid,
  user_email text,
  created_at timestamptz,
  total_count bigint
)
LANGUAGE plpgsql
STABLE
SECURITY DEFINER
SET search_path = ''
AS $$
DECLARE
  v_account_id uuid;
  v_total bigint;
  v_offset integer;
BEGIN
  -- Get event's account for access check
  SELECT e.account_id INTO v_account_id
  FROM public.events e WHERE e.id = p_event_id;

  IF v_account_id IS NULL THEN
    RAISE EXCEPTION 'Event not found';
  END IF;

  IF NOT public.has_role_on_account(v_account_id) THEN
    RAISE EXCEPTION 'Access denied' USING ERRCODE = '42501';
  END IF;

  -- Clamp page size to prevent unbounded queries
  p_page_size := LEAST(GREATEST(p_page_size, 1), 200);
  v_offset := GREATEST(0, (p_page - 1)) * p_page_size;

  -- Get total count
  SELECT count(*) INTO v_total
  FROM public.event_audit_log eal
  WHERE eal.event_id = p_event_id
    AND (p_action_filter IS NULL OR eal.action = p_action_filter);

  -- Return paginated results with user email
  RETURN QUERY
  SELECT
    eal.id,
    eal.action,
    eal.changes,
    eal.metadata,
    eal.user_id,
    u.email::text AS user_email,
    eal.created_at,
    v_total AS total_count
  FROM public.event_audit_log eal
  LEFT JOIN auth.users u ON u.id = eal.user_id
  WHERE eal.event_id = p_event_id
    AND (p_action_filter IS NULL OR eal.action = p_action_filter)
  ORDER BY eal.created_at DESC
  LIMIT p_page_size OFFSET v_offset;
END;
$$;

GRANT EXECUTE ON FUNCTION public.get_event_timeline(uuid, integer, integer, text)
  TO authenticated, service_role;

-- -------------------------------------------------------
-- 3. Booking timeline RPC
-- -------------------------------------------------------

CREATE OR REPLACE FUNCTION public.get_booking_timeline(
  p_booking_id uuid,
  p_page integer DEFAULT 1,
  p_page_size integer DEFAULT 50,
  p_action_filter text DEFAULT NULL
)
RETURNS TABLE (
  id bigint,
  action text,
  changes jsonb,
  metadata jsonb,
  user_id uuid,
  user_email text,
  created_at timestamptz,
  total_count bigint
)
LANGUAGE plpgsql
STABLE
SECURITY DEFINER
SET search_path = ''
AS $$
DECLARE
  v_account_id uuid;
  v_total bigint;
  v_offset integer;
BEGIN
  -- Get booking's account for access check
  SELECT b.account_id INTO v_account_id
  FROM public.bookings b WHERE b.id = p_booking_id;

  IF v_account_id IS NULL THEN
    RAISE EXCEPTION 'Booking not found';
  END IF;

  IF NOT public.has_role_on_account(v_account_id) THEN
    RAISE EXCEPTION 'Access denied' USING ERRCODE = '42501';
  END IF;

  -- Clamp page size to prevent unbounded queries
  p_page_size := LEAST(GREATEST(p_page_size, 1), 200);
  v_offset := GREATEST(0, (p_page - 1)) * p_page_size;

  -- Get total count
  SELECT count(*) INTO v_total
  FROM public.booking_audit_log bal
  WHERE bal.booking_id = p_booking_id
    AND (p_action_filter IS NULL OR bal.action = p_action_filter);

  -- Return paginated results with user email
  RETURN QUERY
  SELECT
    bal.id,
    bal.action,
    bal.changes,
    bal.metadata,
    bal.user_id,
    u.email::text AS user_email,
    bal.created_at,
    v_total AS total_count
  FROM public.booking_audit_log bal
  LEFT JOIN auth.users u ON u.id = bal.user_id
  WHERE bal.booking_id = p_booking_id
    AND (p_action_filter IS NULL OR bal.action = p_action_filter)
  ORDER BY bal.created_at DESC
  LIMIT p_page_size OFFSET v_offset;
END;
$$;

GRANT EXECUTE ON FUNCTION public.get_booking_timeline(uuid, integer, integer, text)
  TO authenticated, service_role;
