import { convexTest } from 'convex-test';
import { beforeAll, describe, expect, test } from 'vitest';

import { api } from '../../convex/_generated/api.js';
import schema from '../../convex/schema';

const modules = import.meta.glob('../../convex/**/*.*s');

const spoonInput = {
  name: 'Editor Spoon',
  provider: 'gitea' as const,
  upstreamOwner: 'upstream',
  upstreamRepo: 'editor',
  upstreamDefaultBranch: 'main',
  upstreamUrl: 'https://git.example.com/upstream/editor',
  forkOwner: 'team',
  forkRepo: 'editor-spoon',
  forkUrl: 'https://git.example.com/team/editor-spoon',
  visibility: 'private' as const,
  maintenanceMode: 'watch' as const,
  syncCadence: 'daily' as const,
  productionRefStrategy: 'default_branch' as const,
};

const seedJob = async (
  t: ReturnType<typeof convexTest>,
  status: 'cancelled' | 'running',
) =>
  await t.mutation(async (ctx) => {
    const now = Date.now();
    const ownerId = await ctx.db.insert('users', {
      email: 'a@b.c',
      name: 'A',
    });
    const spoonId = await ctx.db.insert('spoons', {
      ...spoonInput,
      ownerId,
      status: 'active',
      createdAt: now,
      updatedAt: now,
    });
    const requestId = await ctx.db.insert('agentRequests', {
      spoonId,
      ownerId,
      prompt: 'x',
      status: 'running',
      createdAt: now,
      updatedAt: now,
    });
    return await ctx.db.insert('agentJobs', {
      spoonId,
      ownerId,
      agentRequestId: requestId,
      status,
      prompt: 'x',
      runtime: 'opencode',
      baseBranch: 'main',
      workBranch: 'spoon/x',
      forkOwner: 'team',
      forkRepo: 'editor-spoon',
      forkUrl: 'https://git.example.com/team/editor-spoon',
      upstreamOwner: 'upstream',
      upstreamRepo: 'editor',
      selectedSecretIds: [],
      model: '',
      reasoningEffort: 'medium',
      claimedBy: 'worker-1',
      createdAt: now,
      updatedAt: now,
    });
  });

beforeAll(() => {
  process.env.SPOON_WORKER_TOKEN = 'test-worker-token';
});

describe('updateStatus terminal guard', () => {
  test('ignores writes to a cancelled job', async () => {
    const t = convexTest(schema, modules);
    const jobId = await seedJob(t, 'cancelled');

    const result = await t.mutation(api.agentJobs.updateStatus, {
      workerToken: 'test-worker-token',
      workerId: 'worker-1',
      jobId,
      status: 'running',
    });

    expect(result).toEqual({ success: true, ignored: true });
    const job = await t.run(async (ctx) => await ctx.db.get(jobId));
    expect(job?.status).toBe('cancelled');
  });

  test('accepts writes to a running job', async () => {
    const t = convexTest(schema, modules);
    const jobId = await seedJob(t, 'running');

    const result = await t.mutation(api.agentJobs.updateStatus, {
      workerToken: 'test-worker-token',
      workerId: 'worker-1',
      jobId,
      status: 'checks_running',
    });

    expect(result).toEqual({ success: true });
    const job = await t.run(async (ctx) => await ctx.db.get(jobId));
    expect(job?.status).toBe('checks_running');
  });
});
