import { mutation, query } from "./_generated/server";
import { v } from "convex/values";
import { getAuthUserId } from "@convex-dev/auth/server";
import { nowIso } from "./_utils/time";
import type { Id } from "./_generated/dataModel";

async function requireUserId(ctx: any): Promise<string> {
  const userId = await getAuthUserId(ctx);
  if (userId === null) throw new Error("未登录");
  return String(userId);
}

async function requireWorkspaceMember(ctx: any, workspaceId: string, userId: string) {
  const member = await ctx.db
    .query("workspace_members")
    .withIndex("by_workspace_user", (q: any) => q.eq("workspace_id", workspaceId).eq("user_id", userId))
    .first();
  if (!member) throw new Error("无权限");
  return member;
}

function normalizeGroupName(raw: string): string {
  const name = String(raw ?? "").trim();
  if (!name) throw new Error("群组名称不能为空");
  if (name.length > 50) throw new Error("群组名称最多 50 个字符");
  return name;
}

export const listByWorkspace = query({
  args: { workspaceId: v.string() },
  handler: async (ctx, args) => {
    const userId = await requireUserId(ctx);
    await requireWorkspaceMember(ctx, args.workspaceId, userId);

    const groups = await ctx.db
      .query("groups")
      .withIndex("by_workspace", (q: any) => q.eq("workspace_id", args.workspaceId))
      .collect();

    groups.sort((a: any, b: any) => (a.created_at ?? "").localeCompare(b.created_at ?? ""));
    return groups.map((g: any) => ({
      id: g.id,
      workspace_id: g.workspace_id,
      name: g.name,
      created_by: g.created_by,
      created_at: g.created_at,
      updated_at: g.updated_at,
    }));
  },
});

export const listMineByWorkspace = query({
  args: { workspaceId: v.string() },
  handler: async (ctx, args) => {
    const userId = await requireUserId(ctx);
    await requireWorkspaceMember(ctx, args.workspaceId, userId);

    const memberships = await ctx.db
      .query("group_members")
      .withIndex("by_workspace_user", (q: any) => q.eq("workspace_id", args.workspaceId).eq("user_id", userId))
      .collect();

    const groupsById = new Map<string, any>();
    for (const m of memberships) {
      const group = await ctx.db
        .query("groups")
        .withIndex("by_group_id", (q: any) => q.eq("id", m.group_id))
        .first();
      if (group) {
        groupsById.set(String(group.id), {
          id: group.id,
          workspace_id: group.workspace_id,
          name: group.name,
          created_by: group.created_by,
          created_at: group.created_at,
          updated_at: group.updated_at,
          my_role: m.role,
        });
      }
    }

    const rows = Array.from(groupsById.values());
    rows.sort((a: any, b: any) => String(a.created_at ?? "").localeCompare(String(b.created_at ?? "")));

    // 额外：带上当前用户用户名，前端可用
    const me = await ctx.db.get(userId as Id<"users">);

    return {
      me: { userId, username: me?.name ?? null },
      groups: rows,
    };
  },
});

export const create = mutation({
  args: {
    id: v.string(),
    workspaceId: v.string(),
    name: v.string(),
  },
  handler: async (ctx, args) => {
    const userId = await requireUserId(ctx);
    await requireWorkspaceMember(ctx, args.workspaceId, userId);

    const name = normalizeGroupName(args.name);
    const ts = nowIso();

    const existing = await ctx.db
      .query("groups")
      .withIndex("by_group_id", (q: any) => q.eq("id", args.id))
      .first();
    if (existing) throw new Error("群组已存在");

    await ctx.db.insert("groups", {
      id: args.id,
      workspace_id: args.workspaceId,
      name,
      created_by: userId,
      created_at: ts,
      updated_at: ts,
    });

    await ctx.db.insert("group_members", {
      workspace_id: args.workspaceId,
      group_id: args.id,
      user_id: userId,
      role: "owner",
      created_at: ts,
    });

    return { ok: true, id: args.id };
  },
});

export const rename = mutation({
  args: { groupId: v.string(), name: v.string() },
  handler: async (ctx, args) => {
    const userId = await requireUserId(ctx);
    const group = await ctx.db
      .query("groups")
      .withIndex("by_group_id", (q: any) => q.eq("id", args.groupId))
      .first();
    if (!group) throw new Error("群组不存在");

    await requireWorkspaceMember(ctx, group.workspace_id, userId);

    const membership = await ctx.db
      .query("group_members")
      .withIndex("by_group_user", (q: any) => q.eq("group_id", args.groupId).eq("user_id", userId))
      .first();
    if (!membership || membership.role !== "owner") throw new Error("无权限");

    const ts = nowIso();
    await ctx.db.patch(group._id, { name: normalizeGroupName(args.name), updated_at: ts });
    return { ok: true };
  },
});

export const remove = mutation({
  args: { groupId: v.string() },
  handler: async (ctx, args) => {
    const userId = await requireUserId(ctx);
    const group = await ctx.db
      .query("groups")
      .withIndex("by_group_id", (q: any) => q.eq("id", args.groupId))
      .first();
    if (!group) return { ok: true };

    await requireWorkspaceMember(ctx, group.workspace_id, userId);

    const membership = await ctx.db
      .query("group_members")
      .withIndex("by_group_user", (q: any) => q.eq("group_id", args.groupId).eq("user_id", userId))
      .first();
    if (!membership || membership.role !== "owner") throw new Error("无权限");

    const members = await ctx.db
      .query("group_members")
      .withIndex("by_group", (q: any) => q.eq("group_id", args.groupId))
      .collect();

    const shares = await ctx.db
      .query("document_group_shares")
      .withIndex("by_workspace_group", (q: any) => q.eq("workspace_id", group.workspace_id).eq("group_id", args.groupId))
      .collect();

    const perms = await ctx.db
      .query("document_group_user_permissions")
      .withIndex("by_workspace_group", (q: any) => q.eq("workspace_id", group.workspace_id).eq("group_id", args.groupId))
      .collect();

    for (const m of members) {
      await ctx.db.delete(m._id);
    }
    for (const s of shares) {
      await ctx.db.delete(s._id);
    }
    for (const p of perms) {
      await ctx.db.delete(p._id);
    }
    await ctx.db.delete(group._id);

    return { ok: true };
  },
});
