import { describe, it, expect, beforeAll } from 'vitest';
import * as pulumi from '@pulumi/pulumi';

let captured: Record<string, any> | undefined;

beforeAll(() => {
  pulumi.runtime.setMocks({
    newResource: (args: pulumi.runtime.MockResourceArgs) => {
      // Dynamic resources carry a serialized __provider plus our inputs.
      captured = args.inputs;
      return { id: `${args.inputs.name}-id`, state: args.inputs };
    },
    call: () => ({}),
  });
});

function promiseOf<T>(o: pulumi.Output<T>): Promise<T> {
  return new Promise((resolve) => o.apply(resolve));
}

describe('Llm wrapper', () => {
  it('maps typed args onto a generic {kind:"llm", name, spec, mcpd} resource', async () => {
    // Import after setMocks so resource registration is intercepted.
    const { Llm } = await import('../src/llm');
    const llm = new Llm('homelab-qwen', {
      name: 'qwen3-thinking',
      type: 'openai',
      model: 'qwen3-thinking',
      url: 'http://litellm:4000',
      tier: 'heavy',
      mcpd: { url: 'http://mcpd', token: 'secret-pat' },
    });
    await promiseOf(llm.urn);

    expect(captured).toBeDefined();
    expect(captured!.kind).toBe('llm');
    expect(captured!.name).toBe('qwen3-thinking');
    expect(captured!.spec).toMatchObject({ type: 'openai', model: 'qwen3-thinking', url: 'http://litellm:4000', tier: 'heavy' });
    // name is a top-level field, not part of spec.
    expect(captured!.spec).not.toHaveProperty('name');
    expect(captured!.mcpd).toMatchObject({ url: 'http://mcpd', token: 'secret-pat' });
  });
});
