-- =============================================
-- 配送模块 - RLS（行级安全）与策略（按角色/用户隔离版）
-- 修复说明：
-- - Postgres 的 EXECUTE 只能执行「字符串」，因此 CREATE POLICY 必须包在字符串里。
-- - 本脚本使用 format($pol$ ... $pol$) 生成字符串，避免引号转义问题。
-- - 可重复执行：创建前检查 pg_policies。
--
-- 设计目标：
-- 1) 关闭 UNRESTRICTED：启用 RLS，避免 API 公共可读写。
-- 2) 最小可用：
--    - 配送员（delivery）只能读写自己的配送员档案、以及自己的任务。
--    - 管理员/分析员（admin/analytics）可读取全量数据用于后台与分析。
--    - 其他角色默认无权限。
--
-- 前置假设：
-- - public.ak_users 表存在，且字段：id(UUID), role(TEXT)
-- - ml_delivery_drivers.user_id 可与 auth.uid() 对齐
-- =============================================

-- 0) 开启 RLS
ALTER TABLE public.ml_delivery_drivers ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.ml_delivery_tasks ENABLE ROW LEVEL SECURITY;

-- =========================
-- ml_delivery_drivers 策略
-- =========================
DO $$
BEGIN
  -- 1.1 配送员只能查看自己的档案
  IF NOT EXISTS (
    SELECT 1 FROM pg_policies
    WHERE schemaname='public' AND tablename='ml_delivery_drivers' AND policyname='delivery_can_select_own_driver_profile'
  ) THEN
    EXECUTE format($pol$
      CREATE POLICY delivery_can_select_own_driver_profile
      ON public.ml_delivery_drivers
      FOR SELECT
      USING (
        auth.role() = 'authenticated'
        AND user_id = auth.uid()
        AND EXISTS (
          SELECT 1 FROM public.ak_users u
          WHERE u.id = auth.uid() AND u.role = 'delivery'
        )
      )
    $pol$);
  END IF;

  -- 1.2 配送员只能更新自己的档案
  IF NOT EXISTS (
    SELECT 1 FROM pg_policies
    WHERE schemaname='public' AND tablename='ml_delivery_drivers' AND policyname='delivery_can_update_own_driver_profile'
  ) THEN
    EXECUTE format($pol$
      CREATE POLICY delivery_can_update_own_driver_profile
      ON public.ml_delivery_drivers
      FOR UPDATE
      USING (
        auth.role() = 'authenticated'
        AND user_id = auth.uid()
        AND EXISTS (
          SELECT 1 FROM public.ak_users u
          WHERE u.id = auth.uid() AND u.role = 'delivery'
        )
      )
      WITH CHECK (
        user_id = auth.uid()
      )
    $pol$);
  END IF;

  -- 1.3 管理员/分析员可读全量（后台管理/报表）
  IF NOT EXISTS (
    SELECT 1 FROM pg_policies
    WHERE schemaname='public' AND tablename='ml_delivery_drivers' AND policyname='admin_analytics_can_select_all_delivery_drivers'
  ) THEN
    EXECUTE format($pol$
      CREATE POLICY admin_analytics_can_select_all_delivery_drivers
      ON public.ml_delivery_drivers
      FOR SELECT
      USING (
        auth.role() = 'authenticated'
        AND EXISTS (
          SELECT 1 FROM public.ak_users u
          WHERE u.id = auth.uid() AND u.role IN ('admin','analytics')
        )
      )
    $pol$);
  END IF;

  -- 1.4 管理员可写全量（派单/改派/纠错）
  IF NOT EXISTS (
    SELECT 1 FROM pg_policies
    WHERE schemaname='public' AND tablename='ml_delivery_drivers' AND policyname='admin_can_manage_delivery_drivers'
  ) THEN
    EXECUTE format($pol$
      CREATE POLICY admin_can_manage_delivery_drivers
      ON public.ml_delivery_drivers
      FOR ALL
      USING (
        auth.role() = 'authenticated'
        AND EXISTS (
          SELECT 1 FROM public.ak_users u
          WHERE u.id = auth.uid() AND u.role = 'admin'
        )
      )
      WITH CHECK (
        EXISTS (
          SELECT 1 FROM public.ak_users u
          WHERE u.id = auth.uid() AND u.role = 'admin'
        )
      )
    $pol$);
  END IF;
END $$;

-- =========================
-- ml_delivery_tasks 策略
-- =========================
DO $$
BEGIN
  -- 2.1 配送员只能查看自己的任务
  IF NOT EXISTS (
    SELECT 1 FROM pg_policies
    WHERE schemaname='public' AND tablename='ml_delivery_tasks' AND policyname='delivery_can_select_own_tasks'
  ) THEN
    EXECUTE format($pol$
      CREATE POLICY delivery_can_select_own_tasks
      ON public.ml_delivery_tasks
      FOR SELECT
      USING (
        auth.role() = 'authenticated'
        AND EXISTS (
          SELECT 1
          FROM public.ml_delivery_drivers d
          JOIN public.ak_users u ON u.id = auth.uid()
          WHERE u.role = 'delivery'
            AND d.user_id = auth.uid()
            AND d.id = public.ml_delivery_tasks.driver_id
        )
      )
    $pol$);
  END IF;

  -- 2.2 配送员只能更新自己的任务
  IF NOT EXISTS (
    SELECT 1 FROM pg_policies
    WHERE schemaname='public' AND tablename='ml_delivery_tasks' AND policyname='delivery_can_update_own_tasks'
  ) THEN
    EXECUTE format($pol$
      CREATE POLICY delivery_can_update_own_tasks
      ON public.ml_delivery_tasks
      FOR UPDATE
      USING (
        auth.role() = 'authenticated'
        AND EXISTS (
          SELECT 1
          FROM public.ml_delivery_drivers d
          JOIN public.ak_users u ON u.id = auth.uid()
          WHERE u.role = 'delivery'
            AND d.user_id = auth.uid()
            AND d.id = public.ml_delivery_tasks.driver_id
        )
      )
      WITH CHECK (
        EXISTS (
          SELECT 1
          FROM public.ml_delivery_drivers d
          WHERE d.user_id = auth.uid()
            AND d.id = public.ml_delivery_tasks.driver_id
        )
      )
    $pol$);
  END IF;

  -- 2.3 管理员/分析员可读全量任务
  IF NOT EXISTS (
    SELECT 1 FROM pg_policies
    WHERE schemaname='public' AND tablename='ml_delivery_tasks' AND policyname='admin_analytics_can_select_all_delivery_tasks'
  ) THEN
    EXECUTE format($pol$
      CREATE POLICY admin_analytics_can_select_all_delivery_tasks
      ON public.ml_delivery_tasks
      FOR SELECT
      USING (
        auth.role() = 'authenticated'
        AND EXISTS (
          SELECT 1 FROM public.ak_users u
          WHERE u.id = auth.uid() AND u.role IN ('admin','analytics')
        )
      )
    $pol$);
  END IF;

  -- 2.4 管理员可写全量任务
  IF NOT EXISTS (
    SELECT 1 FROM pg_policies
    WHERE schemaname='public' AND tablename='ml_delivery_tasks' AND policyname='admin_can_manage_delivery_tasks'
  ) THEN
    EXECUTE format($pol$
      CREATE POLICY admin_can_manage_delivery_tasks
      ON public.ml_delivery_tasks
      FOR ALL
      USING (
        auth.role() = 'authenticated'
        AND EXISTS (
          SELECT 1 FROM public.ak_users u
          WHERE u.id = auth.uid() AND u.role = 'admin'
        )
      )
      WITH CHECK (
        EXISTS (
          SELECT 1 FROM public.ak_users u
          WHERE u.id = auth.uid() AND u.role = 'admin'
        )
      )
    $pol$);
  END IF;
END $$;

-- 完成
SELECT 'delivery RLS policies applied' AS message;
