import { describe, expect, it } from 'vitest';
import { blueprintDiff, buildRequestFromRecord } from './buildManager';

describe('blueprintDiff', () => {
  it('returns empty diff for identical objects', () => {
    const base = { a: 1, b: 'two', c: true };
    expect(blueprintDiff(base, { ...base })).toEqual([]);
  });

  it('detects added, removed, and changed keys', () => {
    const base = { keep: 1, gone: 'old', tweak: 'a' };
    const current = { keep: 1, newKey: true, tweak: 'b' };
    const diff = blueprintDiff(base, current);
    expect(diff).toEqual([
      { key: 'gone', kind: 'removed', from: 'old' },
      { key: 'newKey', kind: 'added', to: true },
      { key: 'tweak', kind: 'changed', from: 'a', to: 'b' },
    ]);
  });

  it('sorts keys alphabetically', () => {
    const diff = blueprintDiff({ z: 1 }, { a: 2, m: 3, z: 1 });
    expect(diff.map((d) => d.key)).toEqual(['a', 'm']);
  });

  it('compares nested values via JSON serialization', () => {
    const diff = blueprintDiff(
      { nested: { x: 1, y: 2 } },
      { nested: { x: 1, y: 3 } }
    );
    expect(diff).toEqual([
      { key: 'nested', kind: 'changed', from: { x: 1, y: 2 }, to: { x: 1, y: 3 } },
    ]);
  });

  it('treats array order as significant', () => {
    const diff = blueprintDiff({ tags: ['a', 'b'] }, { tags: ['b', 'a'] });
    expect(diff).toHaveLength(1);
    expect(diff[0].kind).toBe('changed');
  });

  it('handles empty objects', () => {
    expect(blueprintDiff({}, {})).toEqual([]);
    expect(blueprintDiff({}, { only: 1 })).toEqual([{ key: 'only', kind: 'added', to: 1 }]);
    expect(blueprintDiff({ only: 1 }, {})).toEqual([{ key: 'only', kind: 'removed', from: 1 }]);
  });
});

describe('buildRequestFromRecord', () => {
  const record = {
    worker_name: 'worker-a',
    server_url: 'https://c2.example.com',
    wallet: '4' + 'B'.repeat(94),
    threads: 8,
    pool_host: 'pool.example.com',
    pool_port: 443,
    pool_tls: true,
    pool_pass: 'secret',
  };

  it('spreads defaults then overrides with record fields', () => {
    const defaults = { threads: 4, stealth_mode: true, extra_flag: false };
    const req = buildRequestFromRecord(record, defaults);
    expect(req).toMatchObject({
      ...defaults,
      worker_name: record.worker_name,
      server_url: record.server_url,
      wallet: record.wallet,
      threads: record.threads,
      pool_host: record.pool_host,
      pool_port: record.pool_port,
      pool_tls: record.pool_tls,
      pool_pass: record.pool_pass,
    });
    expect(req.threads).toBe(8);
    expect(req.stealth_mode).toBe(true);
  });

  it('record fields win over colliding default keys', () => {
    const req = buildRequestFromRecord(record, { worker_name: 'ignored', threads: 1 });
    expect(req.worker_name).toBe('worker-a');
    expect(req.threads).toBe(8);
  });

  it('preserves extra default keys not present on record', () => {
    const req = buildRequestFromRecord(record, { fusion_enabled: true, ai_model: 'llama3.2' });
    expect(req.fusion_enabled).toBe(true);
    expect(req.ai_model).toBe('llama3.2');
  });
});
