/**
 * v2.0.5: Arena routes — competitive dispatch of the same task to multiple agents.
 *
 * POST /api/arena        — create an arena with 2-5 contestants
 * GET  /api/arena/:id    — get all tasks in an arena
 * POST /api/arena/:id/select/:task_id — mark a task as the arena winner
 */
import type { FastifyInstance } from 'fastify';
import { z } from 'zod';
import type { Sql } from '../db.js';

const ContestantSchema = z.object({
  agent: z.string().max(100).optional(),
  model: z.string().max(200).optional(),
  mode_id: z.string().max(200).optional(),
  thinking_option_id: z.string().max(200).optional(),
});

const CreateArenaBody = z.object({
  project_id: z.string().uuid(),
  input: z.string().min(1).max(64_000),
  contestants: z.array(ContestantSchema).min(2).max(5),
});

interface TaskRow {
  id: string;
  agent: string | null;
  model: string | null;
  mode_id: string | null;
  thinking_option_id: string | null;
  state: string;
}

export function registerArenaRoutes(app: FastifyInstance, sql: Sql): void {
  // POST /api/arena — create a new arena
  app.post('/api/arena', async (req, reply) => {
    const parsed = CreateArenaBody.safeParse(req.body);
    if (!parsed.success) {
      reply.code(400);
      return { error: 'invalid body', details: parsed.error.flatten() };
    }

    const { project_id, input, contestants } = parsed.data;
    const arenaId = crypto.randomUUID();

    const tasks: TaskRow[] = [];
    for (const contestant of contestants) {
      const [task] = await sql<TaskRow[]>`
        INSERT INTO tasks (project_id, input, agent, model, mode_id, thinking_option_id, arena_id)
        VALUES (
          ${project_id},
          ${input},
          ${contestant.agent ?? null},
          ${contestant.model ?? null},
          ${contestant.mode_id ?? null},
          ${contestant.thinking_option_id ?? null},
          ${arenaId}
        )
        RETURNING id, agent, model, mode_id, thinking_option_id, state
      `;
      tasks.push(task!);
    }

    reply.code(201);
    return {
      arena_id: arenaId,
      tasks: tasks.map((t) => ({
        id: t.id,
        agent: t.agent,
        model: t.model,
        mode_id: t.mode_id,
        thinking_option_id: t.thinking_option_id,
        state: t.state,
      })),
    };
  });

  // GET /api/arena/:arena_id — list all tasks in an arena
  app.get<{ Params: { arena_id: string } }>('/api/arena/:arena_id', async (req, reply) => {
    const { arena_id } = req.params;

    // Validate UUID format
    const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
    if (!uuidRegex.test(arena_id)) {
      reply.code(400);
      return { error: 'invalid arena_id format' };
    }

    const tasks = await sql`
      SELECT id, project_id, state, input, output_summary, agent, model, mode_id, thinking_option_id, execution_path, session_id, started_at, ended_at, created_at, arena_id
      FROM tasks
      WHERE arena_id = ${arena_id}
      ORDER BY created_at
    `;

    if (tasks.length === 0) {
      reply.code(404);
      return { error: 'arena not found' };
    }

    return { arena_id, tasks };
  });

  // POST /api/arena/:arena_id/select/:task_id — mark the winner
  app.post<{ Params: { arena_id: string; task_id: string } }>(
    '/api/arena/:arena_id/select/:task_id',
    async (req, reply) => {
      const { arena_id, task_id } = req.params;

      // Verify the task belongs to this arena
      const rows = await sql<{ id: string; state: string; arena_id: string | null }[]>`
        SELECT id, state, arena_id FROM tasks WHERE id = ${task_id}
      `;

      if (rows.length === 0) {
        reply.code(404);
        return { error: 'task not found' };
      }

      const task = rows[0]!;
      if (task.arena_id !== arena_id) {
        reply.code(409);
        return { error: 'task does not belong to this arena' };
      }

      // Mark as selected via output_summary prefix (lightweight — no schema change)
      await sql`
        UPDATE tasks
        SET output_summary = COALESCE('[SELECTED] ' || output_summary, '[SELECTED]')
        WHERE id = ${task_id}
      `;

      return { selected: true, task_id, arena_id };
    }
  );
}
