import { ConvexError, v } from 'convex/values';

import { mutation, query } from './_generated/server';
import {
  getOwnedSpoon,
  getRequiredUserId,
  optionalText,
  requireText,
} from './model';

export const listRecent = query({
  args: { limit: v.optional(v.number()) },
  handler: async (ctx, { limit }) => {
    const ownerId = await getRequiredUserId(ctx);
    return await ctx.db
      .query('agentRequests')
      .withIndex('by_owner', (q) => q.eq('ownerId', ownerId))
      .order('desc')
      .take(limit ?? 25);
  },
});

export const listForSpoon = query({
  args: { spoonId: v.id('spoons'), limit: v.optional(v.number()) },
  handler: async (ctx, { spoonId, limit }) => {
    const ownerId = await getRequiredUserId(ctx);
    await getOwnedSpoon(ctx, spoonId, ownerId);
    return await ctx.db
      .query('agentRequests')
      .withIndex('by_spoon', (q) => q.eq('spoonId', spoonId))
      .order('desc')
      .take(limit ?? 25);
  },
});

export const create = mutation({
  args: {
    spoonId: v.id('spoons'),
    prompt: v.string(),
    targetBranch: v.optional(v.string()),
  },
  handler: async (ctx, args) => {
    const ownerId = await getRequiredUserId(ctx);
    await getOwnedSpoon(ctx, args.spoonId, ownerId);
    const now = Date.now();
    return await ctx.db.insert('agentRequests', {
      spoonId: args.spoonId,
      ownerId,
      prompt: requireText(args.prompt, 'Prompt'),
      status: 'queued',
      requestType: 'future_code_change',
      priority: 'normal',
      source: 'user',
      targetBranch: optionalText(args.targetBranch),
      createdAt: now,
      updatedAt: now,
    });
  },
});

export const updatePrompt = mutation({
  args: {
    requestId: v.id('agentRequests'),
    prompt: v.string(),
    targetBranch: v.optional(v.string()),
  },
  handler: async (ctx, args) => {
    const ownerId = await getRequiredUserId(ctx);
    const request = await ctx.db.get(args.requestId);
    if (request?.ownerId !== ownerId) {
      throw new ConvexError('Agent request not found.');
    }
    if (request.status !== 'draft' && request.status !== 'queued') {
      throw new ConvexError('Only draft or queued requests can be edited.');
    }
    await ctx.db.patch(args.requestId, {
      prompt: requireText(args.prompt, 'Prompt'),
      targetBranch: optionalText(args.targetBranch),
      updatedAt: Date.now(),
    });
    return { success: true };
  },
});

export const cancel = mutation({
  args: { requestId: v.id('agentRequests') },
  handler: async (ctx, { requestId }) => {
    const ownerId = await getRequiredUserId(ctx);
    const request = await ctx.db.get(requestId);
    if (request?.ownerId !== ownerId) {
      throw new ConvexError('Agent request not found.');
    }
    if (request.status !== 'draft' && request.status !== 'queued') {
      throw new ConvexError('Only draft or queued requests can be cancelled.');
    }
    await ctx.db.patch(requestId, {
      status: 'cancelled',
      updatedAt: Date.now(),
    });
    return { success: true };
  },
});
