import type { TojuPluginManifest } from '../../../../shared-kernel';
import { isKnownPluginCapability, validateTojuPluginManifest } from './plugin-manifest-validation.logic';

function createManifest(overrides: Partial<TojuPluginManifest> = {}): TojuPluginManifest {
  return {
    apiVersion: '1.0.0',
    compatibility: {
      minimumTojuVersion: '1.0.0'
    },
    description: 'Adds test behavior.',
    entrypoint: './main.js',
    id: 'test.plugin',
    kind: 'client',
    schemaVersion: 1,
    title: 'Test Plugin',
    version: '1.2.3',
    ...overrides
  };
}

describe('plugin manifest validation', () => {
  it('accepts a valid client plugin manifest', () => {
    const result = validateTojuPluginManifest(createManifest({
      capabilities: ['messages.send', 'ui.settings'],
      events: [
        {
          direction: 'serverRelay',
          eventName: 'test:ping',
          scope: 'server'
        }
      ]
    }));

    expect(result.valid).toBe(true);
    expect(result.manifest?.id).toBe('test.plugin');
    expect(result.issues).toEqual([]);
  });

  it('rejects executable client manifests without an entrypoint', () => {
    const manifest = createManifest({ entrypoint: undefined });
    const result = validateTojuPluginManifest(manifest);

    expect(result.valid).toBe(false);
    expect(result.manifest).toBeUndefined();
    expect(result.issues).toContainEqual({
      message: 'client plugins require an entrypoint',
      path: 'entrypoint',
      severity: 'error'
    });
  });

  it('allows library manifests without an entrypoint', () => {
    const result = validateTojuPluginManifest(createManifest({
      entrypoint: undefined,
      kind: 'library'
    }));

    expect(result.valid).toBe(true);
  });

  it('accepts server-scoped client plugin manifests', () => {
    const result = validateTojuPluginManifest(createManifest({
      scope: 'server'
    }));

    expect(result.valid).toBe(true);
    expect(result.manifest?.scope).toBe('server');
  });

  it('rejects unknown plugin install scopes', () => {
    const result = validateTojuPluginManifest({
      ...createManifest(),
      scope: 'workspace'
    });

    expect(result.valid).toBe(false);
    expect(result.issues).toContainEqual({
      message: 'scope must be client or server',
      path: 'scope',
      severity: 'error'
    });
  });

  it('rejects unknown capabilities and event dimensions', () => {
    const result = validateTojuPluginManifest({
      ...createManifest(),
      capabilities: ['messages.send', 'unknown.power'],
      events: [
        {
          direction: 'serverMagic',
          eventName: 'bad-event',
          scope: 'cosmos'
        }
      ]
    });

    expect(result.valid).toBe(false);
    expect(result.issues.map((issue) => issue.path)).toEqual(expect.arrayContaining([
      'capabilities.1',
      'events.0.direction',
      'events.0.scope'
    ]));
  });

  it('narrows known plugin capabilities', () => {
    expect(isKnownPluginCapability('messages.send')).toBe(true);
    expect(isKnownPluginCapability('messages.destroyEverything')).toBe(false);
  });
});
