// Feature: divisi-metrics, Property 2: Entity JSON round-trip
// **Validates: Requirements 1.12**

import { describe, it, expect } from 'vitest';
import * as fc from 'fast-check';
import {
  works,
  composers,
  payees,
  contracts,
  income,
  transactions,
  costs,
  statements,
  suspenseItems,
  auditEvents,
} from '@/lib/mock-data';

/**
 * Date reviver for JSON.parse — converts ISO 8601 date strings back to Date objects.
 */
function dateReviver(key: string, value: unknown): unknown {
  if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}T/.test(value)) {
    const date = new Date(value);
    if (!isNaN(date.getTime())) return date;
  }
  return value;
}

/**
 * Deep equality check that handles Date objects by comparing their time values.
 */
function deepEqual(a: unknown, b: unknown): boolean {
  if (a instanceof Date && b instanceof Date) {
    return a.getTime() === b.getTime();
  }
  if (a === b) return true;
  if (a === null || b === null) return a === b;
  if (typeof a !== typeof b) return false;
  if (Array.isArray(a) && Array.isArray(b)) {
    if (a.length !== b.length) return false;
    return a.every((val, i) => deepEqual(val, b[i]));
  }
  if (typeof a === 'object' && typeof b === 'object') {
    const aObj = a as Record<string, unknown>;
    const bObj = b as Record<string, unknown>;
    const aKeys = Object.keys(aObj);
    const bKeys = Object.keys(bObj);
    if (aKeys.length !== bKeys.length) return false;
    return aKeys.every((key) => deepEqual(aObj[key], bObj[key]));
  }
  return false;
}

/**
 * Entity collections indexed 0–9, matching the same order as Property 1.
 */
const collections = [
  { label: 'Work', data: works },
  { label: 'Composer', data: composers },
  { label: 'Payee', data: payees },
  { label: 'Contract', data: contracts },
  { label: 'IncomeRecord', data: income },
  { label: 'Transaction', data: transactions },
  { label: 'Cost', data: costs },
  { label: 'Statement', data: statements },
  { label: 'SuspenseItem', data: suspenseItems },
  { label: 'AuditEvent', data: auditEvents },
] as const;

describe('Property 2: Entity JSON round-trip', () => {
  it('serializing any entity to JSON and deserializing back with Date reviver produces an equivalent object', () => {
    fc.assert(
      fc.property(
        fc.integer({ min: 0, max: 9 }),
        fc.integer({ min: 0, max: 999999 }),
        (entityTypeIndex, rawIndex) => {
          const collection = collections[entityTypeIndex];
          const index = rawIndex % collection.data.length;
          const original = collection.data[index];

          // Serialize to JSON
          const json = JSON.stringify(original);

          // Deserialize with Date reviver
          const restored = JSON.parse(json, dateReviver);

          // Verify round-trip equivalence
          expect(deepEqual(original, restored)).toBe(true);
        },
      ),
      { numRuns: 100 },
    );
  });
});
