import { describe, it, expect } from 'vitest';
import { diffEntity } from '@/lib/entity-diff';

describe('diffEntity', () => {
  it('returns changed=false and empty diff for identical objects', () => {
    const old = { name: 'Alice', status: 'active', count: 5 };
    const result = diffEntity(old, { name: 'Alice', status: 'active', count: 5 });
    expect(result).toEqual({ changed: false, diff: {} });
  });

  it('detects a single field change with correct old/new values', () => {
    const old = { name: 'Alice', status: 'active' };
    const result = diffEntity(old, { status: 'inactive' });
    expect(result.changed).toBe(true);
    expect(result.diff).toEqual({
      status: { old: 'active', new: 'inactive' },
    });
  });

  it('detects multiple field changes', () => {
    const old = { name: 'Alice', status: 'active', count: 1 };
    const result = diffEntity(old, { name: 'Bob', status: 'inactive', count: 2 });
    expect(result.changed).toBe(true);
    expect(Object.keys(result.diff)).toHaveLength(3);
    expect(result.diff.name).toEqual({ old: 'Alice', new: 'Bob' });
    expect(result.diff.status).toEqual({ old: 'active', new: 'inactive' });
    expect(result.diff.count).toEqual({ old: 1, new: 2 });
  });

  it('detects null-to-value transition', () => {
    const old: Record<string, unknown> = { note: null };
    const result = diffEntity(old, { note: 'Hello' });
    expect(result.changed).toBe(true);
    expect(result.diff.note).toEqual({ old: null, new: 'Hello' });
  });

  it('detects value-to-null transition', () => {
    const old: Record<string, unknown> = { note: 'Hello' };
    const result = diffEntity(old, { note: null });
    expect(result.changed).toBe(true);
    expect(result.diff.note).toEqual({ old: 'Hello', new: null });
  });

  it('skips createdAt field', () => {
    const now = new Date();
    const old = { name: 'Alice', createdAt: now };
    const result = diffEntity(old, { name: 'Alice', createdAt: new Date() });
    expect(result.changed).toBe(false);
    expect(result.diff).toEqual({});
  });

  it('skips updatedAt field', () => {
    const old = { name: 'Alice', updatedAt: new Date('2020-01-01') };
    const result = diffEntity(old, { name: 'Alice', updatedAt: new Date('2025-01-01') });
    expect(result.changed).toBe(false);
    expect(result.diff).toEqual({});
  });

  it('skips portId field', () => {
    const old = { name: 'Alice', portId: 'port-1' };
    const result = diffEntity(old, { name: 'Alice', portId: 'port-2' });
    expect(result.changed).toBe(false);
    expect(result.diff).toEqual({});
  });

  it('detects nested object (JSON field) changes', () => {
    const old = { metadata: { color: 'red', size: 10 } };
    const result = diffEntity(old, { metadata: { color: 'blue', size: 10 } });
    expect(result.changed).toBe(true);
    expect(result.diff.metadata).toEqual({
      old: { color: 'red', size: 10 },
      new: { color: 'blue', size: 10 },
    });
  });

  it('only compares keys present in newRecord (partial update)', () => {
    const old = { name: 'Alice', status: 'active', count: 99 };
    // Only updating name; status and count should not appear in diff
    const result = diffEntity(old, { name: 'Bob' });
    expect(result.changed).toBe(true);
    expect(Object.keys(result.diff)).toEqual(['name']);
    expect(result.diff.name).toEqual({ old: 'Alice', new: 'Bob' });
  });

  it('returns changed=false when partial update has no actual changes', () => {
    const old = { name: 'Alice', status: 'active', count: 99 };
    const result = diffEntity(old, { name: 'Alice' });
    expect(result.changed).toBe(false);
    expect(result.diff).toEqual({});
  });
});
