-- =====================================================================================
-- RPC: notify-worker safe recipients lookup (RLS-safe)
--
-- 背景：
-- - public.ml_orders 已开启 RLS，PostgREST 在未携带可解码 JWT 时，auth.uid() 为 NULL，
--   直接 SELECT 会被策略过滤为 0 行，导致 notify-worker 报 “order not found for waybill”。
-- - 在一些自托管场景中，Authorization: Bearer <service_role JWT> 可能因 JWT_SECRET 不一致被 PostgREST 拒绝（401 PGRST301）。
--
-- 方案：
-- - 提供 SECURITY DEFINER 的 RPC：只返回订单的收件人映射（user_id / merchant_id）。
-- - 通过请求头 x-notify-worker-token 做显式鉴权（避免把表全局 SELECT 放开）。
--
-- 使用：
-- - notify-worker 调用 POST /rest/v1/rpc/notify_get_order_recipients
--   并携带 header: x-notify-worker-token: <NOTIFY_WORKER_RPC_TOKEN>
-- =====================================================================================

BEGIN;

CREATE OR REPLACE FUNCTION public.notify_get_order_recipients(
  p_order_id UUID DEFAULT NULL,
  p_order_no TEXT DEFAULT NULL
)
RETURNS TABLE (
  id UUID,
  order_no VARCHAR,
  user_id UUID,
  merchant_id UUID
)
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $func$
DECLARE
  headers_json JSON;
  token TEXT;
  expected_token TEXT;
BEGIN
  -- 1) 读取请求头 token（PostgREST 会把 headers 放入 GUC request.headers）
  expected_token := current_setting('app.notify_worker_token', true);
  headers_json := NULLIF(current_setting('request.headers', true), '')::json;
  IF headers_json IS NOT NULL THEN
    token := headers_json->>'x-notify-worker-token';
  END IF;

  IF expected_token IS NULL OR expected_token = '' THEN
    RAISE EXCEPTION 'server misconfigured: app.notify_worker_token is not set';
  END IF;

  IF token IS NULL OR token <> expected_token THEN
    RAISE EXCEPTION 'permission denied: invalid x-notify-worker-token';
  END IF;

  -- 2) 参数校验
  IF (p_order_id IS NULL OR p_order_id::text = '') AND (p_order_no IS NULL OR btrim(p_order_no) = '') THEN
    RAISE EXCEPTION 'p_order_id or p_order_no must be provided';
  END IF;

  -- 3) 返回映射（SECURITY DEFINER 可绕过 RLS；只返回最小必要字段）
  RETURN QUERY
  SELECT o.id, o.order_no, o.user_id, o.merchant_id
  FROM public.ml_orders o
  WHERE (p_order_id IS NOT NULL AND o.id = p_order_id)
     OR (p_order_no IS NOT NULL AND o.order_no = p_order_no)
  LIMIT 1;
END;
$func$;

-- 默认收紧：撤销 PUBLIC，按需授予 anon/authenticated/service_role 执行权限。
REVOKE ALL ON FUNCTION public.notify_get_order_recipients(UUID, TEXT) FROM PUBLIC;

DO $$
BEGIN
  IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'anon') THEN
    GRANT EXECUTE ON FUNCTION public.notify_get_order_recipients(UUID, TEXT) TO anon;
  END IF;
  IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'authenticated') THEN
    GRANT EXECUTE ON FUNCTION public.notify_get_order_recipients(UUID, TEXT) TO authenticated;
  END IF;
  IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'service_role') THEN
    GRANT EXECUTE ON FUNCTION public.notify_get_order_recipients(UUID, TEXT) TO service_role;
  END IF;
END $$;

COMMIT;
