/**
 * POST /proxymodel/replay — stateless content replay through a ProxyModel pipeline.
 *
 * Takes raw content and runs it through a specified ProxyModel,
 * returning the transformed result. Used by the unified console
 * for lab-style side-by-side comparisons without creating temp projects.
 */
import type { FastifyInstance } from 'fastify';
import { executePipeline } from '../proxymodel/executor.js';
import { getProxyModel } from '../proxymodel/loader.js';
import { LLMProviderAdapter } from '../proxymodel/llm-adapter.js';
import { FileCache } from '../proxymodel/file-cache.js';
import type { ProviderRegistry } from '../providers/registry.js';
import type { ContentType, Section } from '../proxymodel/types.js';

interface ReplayRequestBody {
  content: string;
  sourceName: string;
  proxyModel: string;
  contentType?: ContentType;
  provider?: string;
  llmModel?: string;
}

interface ReplayResponse {
  content: string;
  sections?: Section[];
  durationMs: number;
}

// Cache instances per namespace (replay uses varied provider/model combos)
const replayCaches = new Map<string, FileCache>();

function getReplayCache(provider: string, model: string, proxyModel: string): FileCache {
  const ns = `${provider}--${model}--${proxyModel}`;
  let cache = replayCaches.get(ns);
  if (!cache) {
    cache = new FileCache(ns);
    replayCaches.set(ns, cache);
  }
  return cache;
}

export function registerReplayEndpoint(app: FastifyInstance, providerRegistry?: ProviderRegistry | null): void {
  app.post<{ Body: ReplayRequestBody }>('/proxymodel/replay', async (request, reply) => {
    const { content, sourceName, proxyModel: modelName, contentType, provider: providerName, llmModel } = request.body;

    if (!content || typeof content !== 'string') {
      reply.code(400).send({ error: 'content is required and must be a string' });
      return;
    }
    if (!sourceName || typeof sourceName !== 'string') {
      reply.code(400).send({ error: 'sourceName is required' });
      return;
    }
    if (!modelName || typeof modelName !== 'string') {
      reply.code(400).send({ error: 'proxyModel is required' });
      return;
    }

    let proxyModel;
    try {
      proxyModel = await getProxyModel(modelName);
    } catch (err) {
      reply.code(404).send({ error: `ProxyModel '${modelName}' not found: ${err instanceof Error ? err.message : String(err)}` });
      return;
    }

    const llm = providerRegistry
      ? new LLMProviderAdapter(providerRegistry, providerName ?? undefined, llmModel ?? undefined)
      : { complete: async () => '', available: () => false };

    const start = Date.now();
    try {
      const result = await executePipeline({
        content,
        contentType: contentType ?? 'toolResult',
        sourceName,
        projectName: 'replay',
        sessionId: `replay-${Date.now()}`,
        proxyModel,
        llm,
        cache: getReplayCache(providerName ?? 'default', llmModel ?? 'default', modelName),
      });

      const response: ReplayResponse = {
        content: result.content,
        durationMs: Date.now() - start,
      };
      if (result.sections) response.sections = result.sections;

      reply.code(200).send(response);
    } catch (err) {
      reply.code(500).send({
        error: `Pipeline execution failed: ${err instanceof Error ? err.message : String(err)}`,
        durationMs: Date.now() - start,
      });
    }
  });
}
