import type { FastifyInstance } from 'fastify';
import type { ProjectService } from '../services/project.service.js';

export function registerProjectRoutes(app: FastifyInstance, service: ProjectService): void {
  app.get('/api/v1/projects', async () => {
    // RBAC preSerialization hook handles access filtering
    return service.list();
  });

  app.get<{ Params: { id: string } }>('/api/v1/projects/:id', async (request) => {
    return service.resolveAndGet(request.params.id);
  });

  app.post('/api/v1/projects', async (request, reply) => {
    const ownerId = request.userId ?? 'anonymous';
    const project = await service.create(request.body, ownerId);
    reply.code(201);
    return project;
  });

  app.put<{ Params: { id: string } }>('/api/v1/projects/:id', async (request) => {
    const project = await service.resolveAndGet(request.params.id);
    return service.update(project.id, request.body);
  });

  app.delete<{ Params: { id: string } }>('/api/v1/projects/:id', async (request, reply) => {
    const project = await service.resolveAndGet(request.params.id);
    await service.delete(project.id);
    reply.code(204);
  });

  // Generate .mcp.json for a project
  app.get<{ Params: { id: string } }>('/api/v1/projects/:id/mcp-config', async (request) => {
    return service.generateMcpConfig(request.params.id);
  });

  // Attach a server to a project
  app.post<{ Params: { id: string }; Body: { server: string } }>('/api/v1/projects/:id/servers', async (request) => {
    const body = request.body as { server?: string };
    if (!body.server) {
      throw Object.assign(new Error('Missing "server" in request body'), { statusCode: 400 });
    }
    return service.addServer(request.params.id, body.server);
  });

  // Detach a server from a project
  app.delete<{ Params: { id: string; serverName: string } }>('/api/v1/projects/:id/servers/:serverName', async (request, reply) => {
    await service.removeServer(request.params.id, request.params.serverName);
    reply.code(204);
  });

  // List servers in a project (for mcplocal discovery)
  app.get<{ Params: { id: string } }>('/api/v1/projects/:id/servers', async (request) => {
    const project = await service.resolveAndGet(request.params.id);
    return project.servers.map((ps) => ps.server);
  });

  // Get project instructions for LLM (prompt + server list)
  app.get<{ Params: { id: string } }>('/api/v1/projects/:id/instructions', async (request) => {
    const project = await service.resolveAndGet(request.params.id);
    return {
      prompt: project.prompt,
      servers: project.servers.map((ps) => ({
        name: (ps.server as Record<string, unknown>).name as string,
        description: (ps.server as Record<string, unknown>).description as string,
      })),
    };
  });
}
