import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
import { randomUUID } from 'node:crypto';
import { publishJob } from '../services/publish-job.js';
import type { AppContext } from '../app-context.js';

/**
 * Register action submission routes.
 *
 * POST /api/action/submit — enqueue a warm or unload action
 * GET  /api/action/queue/:providerId — get current queue state
 */
export function registerActionRoutes(
  app: FastifyInstance,
  ctx: AppContext,
): void {
  const { actionQueue, fleet, emitter } = ctx;
  app.post('/api/action/submit', async (req: FastifyRequest, reply: FastifyReply) => {
    const body = req.body as Record<string, unknown>;
    const type = body.type as string;
    const providerId = body.providerId as string;
    const model = body.model as string | undefined;
    const confirmed = body.confirmed === true;

    if (!type || !['warm', 'unload'].includes(type)) {
      return reply.status(400).send({ error: 'type must be warm or unload' });
    }
    if (!providerId) {
      return reply.status(400).send({ error: 'providerId is required' });
    }

    const hostState = fleet.hosts.get(providerId);
    if (!hostState || hostState.liveness === 'down') {
      return reply.status(409).send({ error: 'host offline' });
    }

    const action = {
      actionId: randomUUID(),
      type: type as 'warm' | 'unload',
      providerId,
      model,
      confirmed,
      createdAt: new Date(),
    };

    const result = actionQueue.submit(action);

    if (!result.ok) {
      if (result.requiresConfirmation) {
        return reply.status(409).send({
          error: result.error,
          requiresConfirmation: true,
        });
      }
      if (result.pending) {
        return reply.status(429).send({
          error: result.error,
          pending: result.pending,
        });
      }
      return reply.status(409).send({ error: result.error });
    }

    publishJob(emitter, {
      seq: hostState.seq,
      jobType: 'action',
      jobId: action.actionId,
      status: 'queued',
      detail: {
        actionType: action.type,
        providerId: action.providerId,
        model: action.model ?? null,
      },
    });

    return reply.status(202).send({
      actionId: action.actionId,
      status: 'queued',
    });
  });

  app.get('/api/action/queue/:providerId', async (req: FastifyRequest, reply: FastifyReply) => {
    const providerId = req.params as { providerId: string };
    const state = actionQueue.getState(providerId.providerId);

    if (!state) {
      return reply.status(404).send({ error: 'host not found' });
    }

    return reply.send({
      providerId: providerId.providerId,
      depth: state.queue.length,
      running: state.running,
      entries: state.queue.map((e) => ({
        actionId: e.action.actionId,
        type: e.action.type,
        model: e.action.model ?? null,
        status: e.status,
        error: e.error ?? null,
        enqueuedAt: e.enqueuedAt.toISOString(),
      })),
    });
  });
}
