-- ============================================
-- 用户登录 / 注册 - 核心用户资料表结构（创建版 / Create-only）
-- ============================================
-- 用途：创建核心业务用户资料表（ak_users）及其相关函数和 RLS 策略。
-- 特点：
--   1. 不做 DROP/DELETE/TRUNCATE（不清空数据）
--   2. 通过 IF NOT EXISTS + 系统表判断，实现可重复执行
--   3. 职责单一：只负责 ak_users，不涉及其他基础表
--   4. 依赖：应在基础表（01_create_tables.sql）之后执行
-- ============================================

-- ============================================
-- 1. 业务用户资料表 ak_users
-- ============================================

CREATE TABLE IF NOT EXISTS public.ak_users (
  id uuid primary key,
  username text,
  email text,
  gender text,
  birthday date,
  height_cm numeric,
  weight_kg numeric,
  bio text,
  avatar_url text,
  preferred_language text,
  role text,
  school_id text,
  grade_id text,
  class_id text,
  created_at timestamptz default now(),
  updated_at timestamptz default now()
);

-- 中文注释
COMMENT ON TABLE public.ak_users IS '业务用户资料表（与 auth.users 一一对应）';
COMMENT ON COLUMN public.ak_users.id IS '用户ID（等于 auth.users.id）';
COMMENT ON COLUMN public.ak_users.username IS '用户名/昵称';
COMMENT ON COLUMN public.ak_users.email IS '邮箱';
COMMENT ON COLUMN public.ak_users.gender IS '性别';
COMMENT ON COLUMN public.ak_users.birthday IS '生日';
COMMENT ON COLUMN public.ak_users.height_cm IS '身高（厘米）';
COMMENT ON COLUMN public.ak_users.weight_kg IS '体重（公斤）';
COMMENT ON COLUMN public.ak_users.bio IS '个人简介';
COMMENT ON COLUMN public.ak_users.avatar_url IS '头像地址';
COMMENT ON COLUMN public.ak_users.preferred_language IS '偏好语言';
COMMENT ON COLUMN public.ak_users.role IS '角色（如 customer/merchant/admin 等）';
COMMENT ON COLUMN public.ak_users.school_id IS '学校ID（可选）';
COMMENT ON COLUMN public.ak_users.grade_id IS '年级ID（可选）';
COMMENT ON COLUMN public.ak_users.class_id IS '班级ID（可选）';
COMMENT ON COLUMN public.ak_users.created_at IS '创建时间';
COMMENT ON COLUMN public.ak_users.updated_at IS '更新时间';

-- 为 ak_users 添加 updated_at 触发器
-- 注意：通用函数 update_updated_at_column() 在 01_create_tables.sql 中创建
DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'update_ak_users_updated_at') THEN
    EXECUTE 'CREATE TRIGGER update_ak_users_updated_at BEFORE UPDATE ON public.ak_users FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column()';
  END IF;
END $$;

-- ============================================
-- 2. 行级安全策略（RLS）
-- ============================================

-- 启用 RLS
ALTER TABLE public.ak_users ENABLE ROW LEVEL SECURITY;

-- 仅允许本人读写自己的资料
DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='ak_users' AND policyname='ak_users_self_select') THEN
    EXECUTE 'CREATE POLICY "ak_users_self_select" ON public.ak_users FOR SELECT USING (auth.uid() = id)';
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='ak_users' AND policyname='ak_users_self_insert') THEN
    EXECUTE 'CREATE POLICY "ak_users_self_insert" ON public.ak_users FOR INSERT WITH CHECK (auth.uid() = id)';
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='ak_users' AND policyname='ak_users_self_update') THEN
    EXECUTE 'CREATE POLICY "ak_users_self_update" ON public.ak_users FOR UPDATE USING (auth.uid() = id)';
  END IF;
END $$;

-- ============================================
-- 3. 相关函数
-- ============================================

-- 函数1：手动初始化/更新用户资料（可选，供前端调用）
CREATE OR REPLACE FUNCTION public.upsert_user_profile(
  p_user_id uuid,
  p_email text,
  p_username text default null
)
RETURNS public.ak_users
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
  v_username text := coalesce(p_username, split_part(p_email, '@', 1), 'user');
  v_result public.ak_users;
BEGIN
  -- 插入或更新用户资料
  INSERT INTO public.ak_users (id, email, username)
  VALUES (p_user_id, p_email, v_username)
  ON CONFLICT (id) DO UPDATE
  SET
    email = excluded.email,
    username = coalesce(excluded.username, ak_users.username)
  RETURNING * INTO v_result;

  RETURN v_result;
END;
$$;

-- 函数2：供 auth.users 触发器使用，自动创建用户资料
CREATE OR REPLACE FUNCTION public.handle_new_user()
RETURNS trigger
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
BEGIN
  BEGIN
    INSERT INTO public.ak_users (id, email, username)
    VALUES (NEW.id, NEW.email, COALESCE(SPLIT_PART(NEW.email, '@', 1), 'user'))
    ON CONFLICT (id) DO NOTHING;
  EXCEPTION WHEN OTHERS THEN
    -- 重要：不要因为业务表写入失败而阻断 auth.users 的注册事务
    RAISE WARNING 'handle_new_user failed: %', SQLERRM;
  END;

  RETURN NEW;
END;
$$;

-- ============================================
-- 4. 函数授权
-- ============================================

-- upsert_user_profile 只允许已登录用户调用
REVOKE ALL ON FUNCTION public.upsert_user_profile(uuid, text, text) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.upsert_user_profile(uuid, text, text) TO authenticated;

-- handle_new_user 是触发器函数，由系统内部调用，无需对任何角色授权
