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(),
    actionId: v.string(),
  },
  handler: async (ctx, args) => {
    await assertWorkspaceMember(ctx, args.userId, args.workspaceId);
    return await ctx.db
      .query("agent_actions")
      .withIndex("by_action_id", (q) => q.eq("id", args.actionId))
      .first();
  },
});

export const listBySession = query({
  args: {
    userId: v.string(),
    workspaceId: v.string(),
    sessionId: v.string(),
  },
  handler: async (ctx, args) => {
    await assertWorkspaceMember(ctx, args.userId, args.workspaceId);
    return await ctx.db
      .query("agent_actions")
      .withIndex("by_workspace_session", (q) =>
        q.eq("workspace_id", args.workspaceId).eq("session_id", args.sessionId),
      )
      .collect();
  },
});

export const createStarted = mutation({
  args: {
    userId: v.string(),
    workspaceId: v.string(),
    actionId: v.string(),
    sessionId: v.string(),
    actionType: v.string(),
    actor: v.union(v.literal("human"), v.literal("agent"), v.literal("automation")),
    input: v.any(),
    startedAt: v.string(),
  },
  handler: async (ctx, args) => {
    await assertWorkspaceMember(ctx, args.userId, args.workspaceId);
    await ctx.db.insert("agent_actions", {
      id: args.actionId,
      workspace_id: args.workspaceId,
      session_id: args.sessionId,
      action_type: args.actionType,
      status: "running",
      actor: args.actor,
      input: args.input,
      output: null,
      error: null,
      started_at: args.startedAt,
      finished_at: null,
    });
    return { ok: true, actionId: args.actionId };
  },
});

export const markSucceeded = mutation({
  args: {
    userId: v.string(),
    workspaceId: v.string(),
    actionId: v.string(),
    output: v.any(),
    finishedAt: v.string(),
  },
  handler: async (ctx, args) => {
    await assertWorkspaceMember(ctx, args.userId, args.workspaceId);
    const row = await ctx.db
      .query("agent_actions")
      .withIndex("by_action_id", (q) => q.eq("id", args.actionId))
      .first();
    if (!row) throw new Error("action log not found");
    await ctx.db.patch(row._id, {
      status: "succeeded",
      output: args.output,
      finished_at: args.finishedAt,
    });
    return { ok: true };
  },
});

export const markFailed = mutation({
  args: {
    userId: v.string(),
    workspaceId: v.string(),
    actionId: v.string(),
    error: v.string(),
    finishedAt: v.string(),
  },
  handler: async (ctx, args) => {
    await assertWorkspaceMember(ctx, args.userId, args.workspaceId);
    const row = await ctx.db
      .query("agent_actions")
      .withIndex("by_action_id", (q) => q.eq("id", args.actionId))
      .first();
    if (!row) throw new Error("action log not found");
    await ctx.db.patch(row._id, {
      status: "failed",
      error: args.error,
      finished_at: args.finishedAt,
    });
    return { ok: true };
  },
});
