/**
 * Sync-guard for vendored web-ui copies of server-side helpers.
 *
 * Two helpers exist in BOTH `src/utilities/` (server-side, under unit
 * tests) AND `web-ui/src/utils/` (vendored copy bundled by Vite).
 * We keep two copies because the Docker build context is `web-ui/`
 * only — cross-tree imports from `../../../src/...` worked locally
 * but broke production builds.
 *
 * The two copies must stay BEHAVIORALLY identical. This test imports
 * both copies and exercises them on the same fixtures, asserting the
 * outputs match. If they diverge, this test fails loudly; whoever
 * changed one was supposed to change the other.
 *
 * The path-based dynamic import bypasses the unit jest project's
 * `/web-ui/` testPathIgnorePattern (we're not running web-ui tests,
 * we're just importing modules from the web-ui tree to compare them).
 */
import { describe, test, expect, beforeAll } from '@jest/globals';

// Server-side originals.
import * as srvEdgeIds  from '../flowEdgeIds.js';
import * as srvPublish  from '../flowPublish.js';

// Vendored web-ui copies. Plain relative imports — jest's
// testPathIgnorePatterns gates which TEST FILES run (not which modules
// can be imported by other tests), so importing from web-ui/ is fine.
import * as webUiEdgeIds from '../../../web-ui/src/utils/flowEdgeIds.js';
import * as webUiPublish from '../../../web-ui/src/utils/flowPublish.js';

// Fixtures exercising both helpers' interesting branches.
const edgeFixtures = [
  [],
  null,
  undefined,
  'not-an-array',
  [{ source: 'a', target: 'b' }],
  [{ source: 'a', sourceField: 'topic', target: 'b', targetField: 'topic' }],
  [{ id: 'pre-existing-id', source: 'a', target: 'b' }],
  [
    { source: 'a', target: 'b' },
    { source: 'a', target: 'b' },                  // duplicate — needs index tiebreaker
    { id: 'kept', source: 'c', target: 'd' },
  ],
  [null, { source: 'x', target: 'y' }, undefined],
];

const flowFixtures = [
  null,
  undefined,
  'not-an-object',
  { nodes: [], edges: [] },
  {
    schemaVersion: 2,
    description: 'A '.repeat(200),
    nodes: [
      { id: 'in',  type: 'input' },
      { id: 'a',   type: 'agent', data: { agentId: 'agent-real-id', model: 'gpt-5', label: 'A' } },
      { id: 'b',   type: 'agent', data: { agentId: 'another-id', preferredModel: 'kimi' } },
      { id: 'p',   type: 'pause' },
      { id: 'cron',type: 'agent', data: { cron: '0 9 * * *' } },
      { id: 'out', type: 'output' },
    ],
    edges: [{ source: 'in', target: 'a' }, { source: 'a', target: 'b' }],
  },
];

describe('flowEdgeIds — server vs web-ui copy', () => {
  test('exports the same surface', () => {
    expect(typeof webUiEdgeIds.makeEdgeId).toBe('function');
    expect(typeof webUiEdgeIds.ensureEdgeIds).toBe('function');
  });

  test('makeEdgeId outputs match for every fixture edge', () => {
    const cases = [
      [{ source: 'a', target: 'b' }, 0],
      [{ source: 'a', sourceField: 'x', target: 'b', targetField: 'y' }, 7],
      [{}, 0],
      [null, 5],
      [{ source: 'with:colons', target: 'b' }, 0],
    ];
    for (const [edge, idx] of cases) {
      expect(webUiEdgeIds.makeEdgeId(edge, idx)).toBe(srvEdgeIds.makeEdgeId(edge, idx));
    }
  });

  test('ensureEdgeIds outputs match for every fixture array', () => {
    for (const fixture of edgeFixtures) {
      const a = srvEdgeIds.ensureEdgeIds(fixture);
      const b = webUiEdgeIds.ensureEdgeIds(fixture);
      expect(b).toEqual(a);
    }
  });
});

describe('flowPublish — server vs web-ui copy', () => {
  test('exports the same surface', () => {
    expect(typeof webUiPublish.computeFlowPublishMetadata).toBe('function');
    expect(typeof webUiPublish.sanitizeFlowForPublish).toBe('function');
  });

  test('computeFlowPublishMetadata outputs match for every fixture flow', () => {
    for (const flow of flowFixtures) {
      const a = srvPublish.computeFlowPublishMetadata(flow);
      const b = webUiPublish.computeFlowPublishMetadata(flow);
      expect(b).toEqual(a);
    }
  });

  test('sanitizeFlowForPublish outputs match for every fixture flow', () => {
    for (const flow of flowFixtures) {
      const a = srvPublish.sanitizeFlowForPublish(flow);
      const b = webUiPublish.sanitizeFlowForPublish(flow);
      expect(b).toEqual(a);
    }
  });
});
