/**
 * /api/v1/.../personalities — CRUD for agent personalities + prompt bindings.
 *
 * RBAC inherits from `agents` (see `mapUrlToPermission` in main.ts) — only
 * users who can `view/edit/create/delete:agents` can manage that agent's
 * personalities. Personalities never escape their agent: there is no
 * top-level `/api/v1/personalities` listing.
 */
import type { FastifyInstance } from 'fastify';
import type { PersonalityService } from '../services/personality.service.js';
import { NotFoundError, ConflictError } from '../services/mcp-server.service.js';

export function registerPersonalityRoutes(
  app: FastifyInstance,
  service: PersonalityService,
): void {
  app.get<{ Querystring: { agent?: string } }>(
    '/api/v1/personalities',
    async (request, reply) => {
      try {
        if (request.query.agent !== undefined) {
          return await service.listForAgent(request.query.agent);
        }
        return await service.listAll();
      } catch (err) {
        if (err instanceof NotFoundError) {
          reply.code(404);
          return { error: err.message };
        }
        throw err;
      }
    },
  );

  app.get<{ Params: { agentName: string } }>(
    '/api/v1/agents/:agentName/personalities',
    async (request, reply) => {
      try {
        return await service.listForAgent(request.params.agentName);
      } catch (err) {
        if (err instanceof NotFoundError) {
          reply.code(404);
          return { error: err.message };
        }
        throw err;
      }
    },
  );

  app.post<{ Params: { agentName: string } }>(
    '/api/v1/agents/:agentName/personalities',
    async (request, reply) => {
      try {
        const personality = await service.create(request.params.agentName, request.body);
        reply.code(201);
        return personality;
      } catch (err) {
        if (err instanceof NotFoundError) {
          reply.code(404);
          return { error: err.message };
        }
        if (err instanceof ConflictError) {
          reply.code(409);
          return { error: err.message };
        }
        throw err;
      }
    },
  );

  app.get<{ Params: { id: string } }>(
    '/api/v1/personalities/:id',
    async (request, reply) => {
      try {
        return await service.getById(request.params.id);
      } catch (err) {
        if (err instanceof NotFoundError) {
          reply.code(404);
          return { error: err.message };
        }
        throw err;
      }
    },
  );

  app.put<{ Params: { id: string } }>(
    '/api/v1/personalities/:id',
    async (request, reply) => {
      try {
        return await service.update(request.params.id, request.body);
      } catch (err) {
        if (err instanceof NotFoundError) {
          reply.code(404);
          return { error: err.message };
        }
        throw err;
      }
    },
  );

  app.delete<{ Params: { id: string } }>(
    '/api/v1/personalities/:id',
    async (request, reply) => {
      try {
        await service.delete(request.params.id);
        reply.code(204);
        return null;
      } catch (err) {
        if (err instanceof NotFoundError) {
          reply.code(404);
          return { error: err.message };
        }
        throw err;
      }
    },
  );

  // ── Prompt bindings ──

  app.get<{ Params: { id: string } }>(
    '/api/v1/personalities/:id/prompts',
    async (request, reply) => {
      try {
        return await service.listBoundPrompts(request.params.id);
      } catch (err) {
        if (err instanceof NotFoundError) {
          reply.code(404);
          return { error: err.message };
        }
        throw err;
      }
    },
  );

  app.post<{ Params: { id: string } }>(
    '/api/v1/personalities/:id/prompts',
    async (request, reply) => {
      try {
        const binding = await service.attachPrompt(request.params.id, request.body);
        reply.code(201);
        return binding;
      } catch (err) {
        if (err instanceof NotFoundError) {
          reply.code(404);
          return { error: err.message };
        }
        if (err instanceof ConflictError) {
          reply.code(409);
          return { error: err.message };
        }
        throw err;
      }
    },
  );

  app.delete<{ Params: { id: string; promptId: string } }>(
    '/api/v1/personalities/:id/prompts/:promptId',
    async (request, reply) => {
      try {
        await service.detachPrompt(request.params.id, request.params.promptId);
        reply.code(204);
        return null;
      } catch (err) {
        if (err instanceof NotFoundError) {
          reply.code(404);
          return { error: err.message };
        }
        throw err;
      }
    },
  );
}
