import type { FastifyInstance } from 'fastify';
import type { SecretBackendService } from '../services/secret-backend.service.js';
import { SecretBackendInUseError } from '../services/secret-backend.service.js';
import { NotFoundError, ConflictError } from '../services/mcp-server.service.js';

export function registerSecretBackendRoutes(
  app: FastifyInstance,
  service: SecretBackendService,
): void {
  app.get('/api/v1/secretbackends', async () => {
    const rows = await service.list();
    return rows.map(redactConfig);
  });

  app.get<{ Params: { id: string } }>('/api/v1/secretbackends/:id', async (request) => {
    const row = await service.getById(request.params.id);
    return redactConfig(row);
  });

  app.post('/api/v1/secretbackends', async (request, reply) => {
    try {
      const row = await service.create(request.body as {
        name: string;
        type: string;
        config?: Record<string, unknown>;
        isDefault?: boolean;
        description?: string;
      });
      reply.code(201);
      return redactConfig(row);
    } catch (err) {
      if (err instanceof ConflictError) {
        reply.code(409);
        return { error: err.message };
      }
      throw err;
    }
  });

  app.put<{ Params: { id: string } }>('/api/v1/secretbackends/:id', async (request) => {
    const row = await service.update(request.params.id, request.body as {
      config?: Record<string, unknown>;
      isDefault?: boolean;
      description?: string;
    });
    return redactConfig(row);
  });

  app.post<{ Params: { id: string } }>('/api/v1/secretbackends/:id/default', async (request) => {
    const row = await service.setDefault(request.params.id);
    return redactConfig(row);
  });

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

/**
 * Strip any value from `config` whose key looks like a credential, and replace
 * tokenSecretRef with a short description. Prevents accidental exposure via
 * GET responses.
 */
function redactConfig<T extends { config: unknown }>(row: T): T {
  const config = (row.config ?? {}) as Record<string, unknown>;
  const cleaned: Record<string, unknown> = {};
  for (const [k, v] of Object.entries(config)) {
    if (/token|secret|password|key/i.test(k) && typeof v === 'string') {
      cleaned[k] = '***';
    } else {
      cleaned[k] = v;
    }
  }
  return { ...row, config: cleaned };
}
