import { describe, test, expect } from 'vitest';
import { deriveVirtualRows, VIRTUAL_CHILD_PROPS } from './layers-virtual-rows';

describe('deriveVirtualRows', () => {
  test('returns one row per item, labelled by the registered field', () => {
    const rows = deriveVirtualRows('Features Grid', {
      features: [{ title: 'Fast' }, { title: 'Secure' }],
    });
    expect(rows).toEqual([
      { index: 0, label: 'Fast' },
      { index: 1, label: 'Secure' },
    ]);
  });

  test('falls back to "<Fallback> N" when the label field is missing or blank', () => {
    const rows = deriveVirtualRows('Features Grid', {
      features: [{ title: '' }, { description: 'no title key' }],
    });
    expect(rows).toEqual([
      { index: 0, label: 'Feature 1' },
      { index: 1, label: 'Feature 2' },
    ]);
  });

  test('trims and truncates a long label to 40 characters with an ellipsis', () => {
    const long = 'x'.repeat(60);
    const rows = deriveVirtualRows('Features Grid', { features: [{ title: `  ${long}  ` }] });
    expect(rows[0].label).toHaveLength(41);
    expect(rows[0].label.endsWith('…')).toBe(true);
  });

  test('an unregistered component yields no rows', () => {
    expect(deriveVirtualRows('Heading', { text: 'hi' })).toEqual([]);
  });

  test('a missing or non-array prop yields no rows instead of throwing', () => {
    expect(deriveVirtualRows('Tabs', {})).toEqual([]);
    expect(deriveVirtualRows('Tabs', { tabs: 'not an array' })).toEqual([]);
    expect(deriveVirtualRows('Tabs', { tabs: null })).toEqual([]);
  });

  test('a non-object item still gets a fallback label', () => {
    expect(deriveVirtualRows('Menu', { links: ['raw string'] })).toEqual([
      { index: 0, label: 'Link 1' },
    ]);
  });

  test('Hero, Call to Action and CTA Section derive rows from their shared ctas prop', () => {
    const ctas = [
      { text: 'Get Started', href: '#', variant: 'primary' },
      { text: 'Learn More', href: '#learn', variant: 'outline' },
    ];
    expect(deriveVirtualRows('Hero', { ctas })).toEqual([
      { index: 0, label: 'Get Started' },
      { index: 1, label: 'Learn More' },
    ]);
    expect(deriveVirtualRows('Call to Action', { ctas })).toEqual([
      { index: 0, label: 'Get Started' },
      { index: 1, label: 'Learn More' },
    ]);
    expect(deriveVirtualRows('CTA Section', { ctas })).toEqual([
      { index: 0, label: 'Get Started' },
      { index: 1, label: 'Learn More' },
    ]);
  });

  test('a CTA with no text falls back to "Button N"', () => {
    const rows = deriveVirtualRows('Hero', {
      ctas: [{ href: '#' }, { text: '', href: '#empty' }],
    });
    expect(rows).toEqual([
      { index: 0, label: 'Button 1' },
      { index: 1, label: 'Button 2' },
    ]);
  });

  test('every registry entry has a non-empty prop, label and fallback', () => {
    for (const [name, spec] of Object.entries(VIRTUAL_CHILD_PROPS)) {
      expect(spec.prop, `${name}.prop`).toBeTruthy();
      expect(spec.label, `${name}.label`).toBeTruthy();
      expect(spec.fallback, `${name}.fallback`).toBeTruthy();
    }
  });
});
