import { mutation, query } from "./_generated/server";
import { v } from "convex/values";
import { nowIso } from "./_utils/time";
import type { MutationCtx, QueryCtx } from "./_generated/server";

async function assertWorkspaceMember(
  ctx: QueryCtx | MutationCtx,
  userId: string,
  workspaceId: string,
) {
  const membership = await ctx.db
    .query("workspace_members")
    .withIndex("by_workspace_user", (q) =>
      q.eq("workspace_id", workspaceId).eq("user_id", userId),
    )
    .first();
  if (!membership) {
    throw new Error("无权访问该工作空间");
  }
  return membership;
}

export const getById = query({
  args: {
    userId: v.string(),
    workspaceId: v.string(),
    id: v.string(),
  },
  handler: async (ctx, args) => {
    await assertWorkspaceMember(ctx, args.userId, args.workspaceId);
    return await ctx.db
      .query("pages")
      .withIndex("by_page_id", (q) => q.eq("id", args.id))
      .first();
  },
});

export const listByWorkspace = query({
  args: {
    userId: v.string(),
    workspaceId: v.string(),
  },
  handler: async (ctx, args) => {
    await assertWorkspaceMember(ctx, args.userId, args.workspaceId);
    return await ctx.db
      .query("pages")
      .withIndex("by_workspace", (q) => q.eq("workspace_id", args.workspaceId))
      .collect();
  },
});

export const create = mutation({
  args: {
    userId: v.string(),
    id: v.string(),
    workspaceId: v.string(),
    parentId: v.union(v.string(), v.null()),
    title: v.string(),
    accessScope: v.union(
      v.literal("private"),
      v.literal("shared"),
      v.literal("public"),
    ),
  },
  handler: async (ctx, args) => {
    await assertWorkspaceMember(ctx, args.userId, args.workspaceId);
    const ts = nowIso();
    await ctx.db.insert("pages", {
      id: args.id,
      workspace_id: args.workspaceId,
      parent_id: args.parentId,
      title: args.title,
      access_scope: args.accessScope,
      block_ids: [],
      child_page_ids: [],
      asset_ids: [],
      created_by: args.userId,
      created_at: ts,
      updated_at: ts,
      deleted_at: null,
    });
    return { ok: true, id: args.id };
  },
});

export const rename = mutation({
  args: {
    userId: v.string(),
    workspaceId: v.string(),
    id: v.string(),
    title: v.string(),
  },
  handler: async (ctx, args) => {
    await assertWorkspaceMember(ctx, args.userId, args.workspaceId);
    const page = await ctx.db
      .query("pages")
      .withIndex("by_page_id", (q) => q.eq("id", args.id))
      .first();
    if (!page) throw new Error("页面不存在");
    await ctx.db.patch(page._id, {
      title: args.title,
      updated_at: nowIso(),
    });
    return { ok: true };
  },
});

export const move = mutation({
  args: {
    userId: v.string(),
    workspaceId: v.string(),
    id: v.string(),
    parentId: v.union(v.string(), v.null()),
  },
  handler: async (ctx, args) => {
    await assertWorkspaceMember(ctx, args.userId, args.workspaceId);
    const page = await ctx.db
      .query("pages")
      .withIndex("by_page_id", (q) => q.eq("id", args.id))
      .first();
    if (!page) throw new Error("页面不存在");
    await ctx.db.patch(page._id, {
      parent_id: args.parentId,
      updated_at: nowIso(),
    });
    return { ok: true };
  },
});

export const archive = mutation({
  args: {
    userId: v.string(),
    workspaceId: v.string(),
    id: v.string(),
  },
  handler: async (ctx, args) => {
    await assertWorkspaceMember(ctx, args.userId, args.workspaceId);
    const page = await ctx.db
      .query("pages")
      .withIndex("by_page_id", (q) => q.eq("id", args.id))
      .first();
    if (!page) throw new Error("页面不存在");
    const ts = nowIso();
    await ctx.db.patch(page._id, {
      deleted_at: ts,
      updated_at: ts,
    });
    return { ok: true };
  },
});
