import { describe, it, expect } from 'vitest';
import Fastify from 'fastify';
import { registerProxymodelEndpoint } from '../src/http/proxymodel-endpoint.js';

describe('ProxyModel endpoint', () => {
  it('GET /proxymodels returns built-in models and plugins', async () => {
    const app = Fastify({ logger: false });
    registerProxymodelEndpoint(app);
    await app.ready();

    const res = await app.inject({ method: 'GET', url: '/proxymodels' });
    expect(res.statusCode).toBe(200);

    const body = res.json<Array<{ name: string; source: string; type: string }>>();
    expect(Array.isArray(body)).toBe(true);

    const names = body.map((m) => m.name);
    // YAML pipelines
    expect(names).toContain('default');
    expect(names).toContain('subindex');
    // TypeScript plugins
    expect(names).toContain('gate');
    expect(names).toContain('content-pipeline');

    // Pipeline entries have pipeline-specific fields
    const pipelines = body.filter((m) => m.type === 'pipeline');
    for (const model of pipelines) {
      expect(model).toHaveProperty('controller');
      expect(model).toHaveProperty('stages');
      expect(model).toHaveProperty('cacheable');
    }

    // Plugin entries have plugin-specific fields
    const plugins = body.filter((m) => m.type === 'plugin');
    for (const model of plugins) {
      expect(model).toHaveProperty('hooks');
    }

    await app.close();
  });

  it('GET /proxymodels/:name returns a pipeline model', async () => {
    const app = Fastify({ logger: false });
    registerProxymodelEndpoint(app);
    await app.ready();

    const res = await app.inject({ method: 'GET', url: '/proxymodels/default' });
    expect(res.statusCode).toBe(200);

    const body = res.json<{ name: string; source: string; type: string; controller: string; stages: unknown[] }>();
    expect(body.name).toBe('default');
    expect(body.source).toBe('built-in');
    expect(body.type).toBe('pipeline');
    expect(body.controller).toBe('gate');
    expect(Array.isArray(body.stages)).toBe(true);
    expect(body.stages.length).toBeGreaterThan(0);

    await app.close();
  });

  it('GET /proxymodels/:name returns a plugin', async () => {
    const app = Fastify({ logger: false });
    registerProxymodelEndpoint(app);
    await app.ready();

    const res = await app.inject({ method: 'GET', url: '/proxymodels/gate' });
    expect(res.statusCode).toBe(200);

    const body = res.json<{ name: string; source: string; type: string; hooks: string[] }>();
    expect(body.name).toBe('gate');
    expect(body.source).toBe('built-in');
    expect(body.type).toBe('plugin');
    expect(Array.isArray(body.hooks)).toBe(true);
    expect(body.hooks).toContain('onToolsList');

    await app.close();
  });

  it('GET /proxymodels/:name returns 404 for unknown model', async () => {
    const app = Fastify({ logger: false });
    registerProxymodelEndpoint(app);
    await app.ready();

    const res = await app.inject({ method: 'GET', url: '/proxymodels/nonexistent' });
    expect(res.statusCode).toBe(404);

    const body = res.json<{ error: string }>();
    expect(body.error).toContain('nonexistent');

    await app.close();
  });

  it('GET /proxymodels/subindex returns subindex model details', async () => {
    const app = Fastify({ logger: false });
    registerProxymodelEndpoint(app);
    await app.ready();

    const res = await app.inject({ method: 'GET', url: '/proxymodels/subindex' });
    expect(res.statusCode).toBe(200);

    const body = res.json<{ name: string; cacheable: boolean; stages: Array<{ type: string }> }>();
    expect(body.name).toBe('subindex');
    expect(body.cacheable).toBe(true);
    expect(body.stages.some((s) => s.type === 'section-split')).toBe(true);

    await app.close();
  });
});
