import { describe, expect, it } from 'vitest'
import type { FieldGroup as LegacyFieldGroup } from './model.js'
import {
  isFieldDefinitionIntegrityError,
  legacyFieldGroupToFinalDefinition,
  materializeLegacyFieldDefinitionVersion,
  referencedFieldDefinitionVersions,
} from './definitions.js'
import type { FieldValueNodeRow } from './schema.js'

const legacy = {
  key: 'product_details',
  label: 'Product details',
  location: { entityType: 'product', subType: 'shoe' },
  position: 4,
  fields: [
    { type: 'text', key: 'material', label: 'Material', maxLength: 80 },
    { type: 'select', key: 'sizes', label: 'Sizes', multiple: true, options: [
      { value: '40', label: '40' },
      { value: '41', label: '41' },
    ] },
    { type: 'relationship', key: 'brand', label: 'Brand', targetEntityType: 'brand', multiple: false },
  ],
} satisfies LegacyFieldGroup

describe('legacy field definition materialization', () => {
  it('converts the legacy group into a final immutable parser-valid revision', async () => {
    const definition = legacyFieldGroupToFinalDefinition(legacy)
    expect(definition).toMatchObject({
      key: 'product_details',
      title: 'Product details',
      active: true,
      order: 4,
      location: [[
        { parameter: 'entityType', operator: 'eq', value: 'product' },
        { parameter: 'subType', operator: 'eq', value: 'shoe' },
      ]],
    })
    expect(definition.fields).toEqual(expect.arrayContaining([
      expect.objectContaining({ key: 'material', type: 'text' }),
      expect.objectContaining({ key: 'sizes', type: 'select', settings: expect.objectContaining({ multiple: true }) }),
      expect.objectContaining({ key: 'brand', type: 'relationship', settings: expect.objectContaining({ max: 1 }) }),
    ]))

    const version = await materializeLegacyFieldDefinitionVersion(legacy)
    expect(version).toMatchObject({ groupKey: 'product_details', revision: 1, origin: 'db' })
    expect(version.canonicalHash).toMatch(/^[a-f0-9]{64}$/)
    expect(Object.isFrozen(version)).toBe(true)
    expect(Object.isFrozen(version.definition)).toBe(true)
  })

  it('deduplicates exact immutable definition references from recursive nodes', () => {
    const node = (groupKey: string, revision: number): FieldValueNodeRow => ({
      nodeId: `${groupKey}-${revision}`,
      entityType: 'product',
      entityId: 'p1',
      groupKey,
      definitionRevision: revision,
      fieldKey: 'name',
      path: '/f:name',
      parentNodeId: null,
      rowId: null,
      layoutKey: null,
      nodeKind: 'leaf',
      ordinal: 0,
      isNull: false,
      valueText: 'x',
      valueNumber: null,
      valueBoolean: null,
      valueDateTime: null,
      valueRef: null,
      valueJson: null,
    })
    expect(referencedFieldDefinitionVersions([
      node('g2', 1), node('g1', 2), node('g1', 2),
    ])).toEqual([
      { groupKey: 'g1', revision: 2 },
      { groupKey: 'g2', revision: 1 },
    ])
  })

  it('exposes structural integrity errors without accepting arbitrary lookalikes', () => {
    expect(isFieldDefinitionIntegrityError({ code: 'definition-not-found', groupKey: 'g', revision: 1, detail: 'missing' })).toBe(true)
    expect(isFieldDefinitionIntegrityError({ code: 'definition-not-found', groupKey: 'g', revision: '1', detail: 'missing' })).toBe(false)
  })
})
