/**
 * Property-Based Test: Filter predicate correctness
 *
 * Feature: compliance-nonmetric-filters, Property 2: Filter predicate correctness
 * **Validates: Requirements 3.1, 5.2, 5.3, 5.4**
 *
 * For any filter state and any set of devices: when null, all devices pass;
 * when metric, exactly devices with matching metric_id in ids pass;
 * when nonmetric, exactly devices with matching metric_id pass.
 */
import fc from 'fast-check';

// Replicate the filter predicate logic from CompliancePage
function applyFilter(devices, filterState) {
    return devices.filter(d => {
        if (!filterState) return true;
        if (filterState.type === 'metric') return d.failing_metrics.some(m => filterState.ids.includes(m.metric_id));
        if (filterState.type === 'nonmetric') return d.failing_metrics.some(m => m.metric_id === filterState.id);
        return true;
    });
}

// Generators
const metricIdArb = fc.stringMatching(/^[A-Za-z0-9_.]{1,20}$/);

const failingMetricArb = fc.record({
    metric_id: metricIdArb,
    metric_desc: fc.constant(''),
    category: fc.constant(''),
});

const deviceArb = fc.record({
    hostname: fc.string({ minLength: 1, maxLength: 30 }),
    failing_metrics: fc.array(failingMetricArb, { minLength: 0, maxLength: 8 }),
});

const devicesArb = fc.array(deviceArb, { minLength: 0, maxLength: 20 });

const filterStateArb = fc.oneof(
    fc.constant(null),
    fc.array(metricIdArb, { minLength: 1, maxLength: 5 }).map(ids => ({ type: 'metric', ids })),
    metricIdArb.map(id => ({ type: 'nonmetric', id }))
);

describe('Compliance Non-Metric Filter — Property 2: Filter predicate correctness', () => {
    it('when filterState is null, all devices pass', () => {
        fc.assert(
            fc.property(devicesArb, (devices) => {
                const result = applyFilter(devices, null);
                expect(result.length).toBe(devices.length);
            }),
            { numRuns: 100 }
        );
    });

    it('when filterState is metric, exactly devices with a matching metric_id pass', () => {
        fc.assert(
            fc.property(devicesArb, fc.array(metricIdArb, { minLength: 1, maxLength: 5 }), (devices, ids) => {
                const filterState = { type: 'metric', ids };
                const result = applyFilter(devices, filterState);

                const expected = devices.filter(d =>
                    d.failing_metrics.some(m => ids.includes(m.metric_id))
                );
                expect(result).toEqual(expected);
            }),
            { numRuns: 100 }
        );
    });

    it('when filterState is nonmetric, exactly devices with that metric_id pass', () => {
        fc.assert(
            fc.property(devicesArb, metricIdArb, (devices, id) => {
                const filterState = { type: 'nonmetric', id };
                const result = applyFilter(devices, filterState);

                const expected = devices.filter(d =>
                    d.failing_metrics.some(m => m.metric_id === id)
                );
                expect(result).toEqual(expected);
            }),
            { numRuns: 100 }
        );
    });
});
