/**
 * ProxyModel discovery endpoints.
 *
 * GET /proxymodels       → list all available proxymodels (YAML pipelines + TypeScript plugins)
 * GET /proxymodels/:name → get a single proxymodel by name
 */
import type { FastifyInstance } from 'fastify';
import { loadProxyModels } from '../proxymodel/loader.js';
import { loadPlugins } from '../proxymodel/plugin-loader.js';
import type { ProxyModelPlugin } from '../proxymodel/plugin.js';
import { createGatePlugin } from '../proxymodel/plugins/gate.js';
import { createContentPipelinePlugin } from '../proxymodel/plugins/content-pipeline.js';
import { createDefaultPlugin } from '../proxymodel/plugins/default.js';

interface ProxyModelSummary {
  name: string;
  source: 'built-in' | 'local';
  type: 'pipeline' | 'plugin';
  controller?: string;
  stages?: string[];
  appliesTo?: string[];
  cacheable?: boolean;
  extends?: readonly string[];
  hooks?: string[];
  description?: string;
}

/** Built-in plugin factories */
const BUILT_IN_PLUGINS = [
  createGatePlugin(),
  createContentPipelinePlugin(),
  createDefaultPlugin(),
];

export function registerProxymodelEndpoint(app: FastifyInstance): void {
  // GET /proxymodels — list all
  app.get('/proxymodels', async (_request, reply) => {
    const result: ProxyModelSummary[] = [];

    // Load YAML pipeline models
    const models = await loadProxyModels();
    for (const model of models.values()) {
      result.push({
        name: model.metadata.name,
        source: model.source,
        type: 'pipeline',
        controller: model.spec.controller,
        stages: model.spec.stages.map((s) => s.type),
        appliesTo: model.spec.appliesTo,
        cacheable: model.spec.cacheable,
      });
    }

    // Load TypeScript plugins (built-in + user)
    const pipelineNames = new Set(result.map((r) => r.name));
    const registry = await loadPlugins(BUILT_IN_PLUGINS);
    for (const entry of registry.list()) {
      if (pipelineNames.has(entry.name)) continue; // Already listed as pipeline
      result.push({
        name: entry.name,
        source: entry.source,
        type: 'plugin',
        extends: entry.plugin.extends ?? [],
        hooks: getPluginHooks(entry.plugin),
        description: entry.plugin.description ?? '',
      });
    }

    reply.code(200).send(result);
  });

  // GET /proxymodels/stages — list all available stages
  // Must be registered before :name to avoid being caught by the param route
  app.get('/proxymodels/stages', async (_request, reply) => {
    const { listStages } = await import('../proxymodel/stage-registry.js');
    reply.code(200).send(listStages());
  });

  // POST /proxymodels/reload — force reload custom stages from disk
  app.post('/proxymodels/reload', async (_request, reply) => {
    const { reloadStages } = await import('../proxymodel/watcher.js');
    const result = await reloadStages();
    reply.code(200).send(result);
  });

  // GET /proxymodels/:name — single model details
  app.get<{ Params: { name: string } }>('/proxymodels/:name', async (request, reply) => {
    const { name } = request.params;

    // Check YAML pipelines first
    const models = await loadProxyModels();
    const model = models.get(name);
    if (model) {
      reply.code(200).send({
        name: model.metadata.name,
        source: model.source,
        type: 'pipeline',
        controller: model.spec.controller,
        controllerConfig: model.spec.controllerConfig,
        stages: model.spec.stages,
        appliesTo: model.spec.appliesTo,
        cacheable: model.spec.cacheable,
      });
      return;
    }

    // Check TypeScript plugins
    const registry = await loadPlugins(BUILT_IN_PLUGINS);
    const entry = registry.get(name);
    if (entry) {
      reply.code(200).send({
        name: entry.name,
        source: entry.source,
        type: 'plugin',
        extends: entry.plugin.extends ?? [],
        hooks: getPluginHooks(entry.plugin),
        description: entry.plugin.description ?? null,
      });
      return;
    }

    reply.code(404).send({ error: `ProxyModel '${name}' not found` });
  });
}

function getPluginHooks(plugin: ProxyModelPlugin): string[] {
  const hookNames = [
    'onSessionCreate', 'onSessionDestroy', 'onInitialize',
    'onToolsList', 'onToolCallBefore', 'onToolCallAfter',
    'onResourcesList', 'onResourceRead', 'onPromptsList', 'onPromptGet',
  ] as const;
  return hookNames.filter((h) => typeof plugin[h] === 'function');
}
