/**
 * Property-Based Test: Section Ordering
 *
 * Feature: queue-collapsible-sections, Property 2: Section Ordering
 * **Validates: Requirements 1.3, 1.4**
 *
 * For any array of queue items, the Inventory section (if present) is always
 * the first element, and all vendor sections are sorted alphabetically by label.
 */
import fc from 'fast-check';

// Inline grouping logic (mirrors the implementation in IvantiTodoQueuePage)
function groupQueueItems(visibleItems) {
  const INVENTORY_TYPES = new Set(['CARD', 'GRANITE', 'DECOM']);
  const inventoryItems = [];
  const vendorMap = new Map();
  for (const item of visibleItems) {
    if (INVENTORY_TYPES.has(item.workflow_type)) {
      inventoryItems.push(item);
    } else {
      const vendor = item.vendor?.trim() || 'Unknown';
      if (!vendorMap.has(vendor)) vendorMap.set(vendor, []);
      vendorMap.get(vendor).push(item);
    }
  }
  const sections = [];
  if (inventoryItems.length > 0) {
    sections.push({ key: 'inventory', label: 'Inventory', type: 'inventory', items: inventoryItems });
  }
  const sortedVendors = [...vendorMap.entries()].sort((a, b) => a[0].localeCompare(b[0]));
  for (const [vendor, items] of sortedVendors) {
    sections.push({ key: `vendor:${vendor}`, label: vendor, type: 'vendor', items });
  }
  return sections;
}

// Generator for queue items with random workflow types and vendors
const workflowTypeArb = fc.constantFrom('CARD', 'GRANITE', 'DECOM', 'FP', 'Archer');

const vendorArb = fc.oneof(
  fc.constant(null),
  fc.constant(undefined),
  fc.constant(''),
  fc.constant('  '),
  fc.stringMatching(/^[A-Za-z][A-Za-z0-9 ]{0,14}$/)
);

const queueItemArb = fc.record({
  id: fc.integer({ min: 1, max: 100000 }),
  workflow_type: workflowTypeArb,
  vendor: vendorArb,
  hostname: fc.string({ minLength: 1, maxLength: 20 }),
  status: fc.constant('pending'),
});

const queueItemsArb = fc.array(queueItemArb, { minLength: 0, maxLength: 50 });

describe('Queue Grouping — Property 2: Section Ordering', () => {
  it('Inventory section (if present) is always the first element', () => {
    fc.assert(
      fc.property(queueItemsArb, (items) => {
        const sections = groupQueueItems(items);

        const inventoryIndex = sections.findIndex(s => s.type === 'inventory');

        // If inventory section exists, it must be at index 0
        if (inventoryIndex !== -1) {
          expect(inventoryIndex).toBe(0);
        }
      }),
      { numRuns: 500 }
    );
  });

  it('Vendor sections are sorted alphabetically by label', () => {
    fc.assert(
      fc.property(queueItemsArb, (items) => {
        const sections = groupQueueItems(items);

        const vendorSections = sections.filter(s => s.type === 'vendor');

        // Each consecutive pair of vendor sections must be in alphabetical order
        for (let i = 1; i < vendorSections.length; i++) {
          const prev = vendorSections[i - 1].label;
          const curr = vendorSections[i].label;
          expect(prev.localeCompare(curr)).toBeLessThanOrEqual(0);
        }
      }),
      { numRuns: 500 }
    );
  });
});
