/**
 * Property-Based Tests: Ivanti Queue Remediation — Vendor Validation
 *
 * Feature: ivanti-queue-remediation
 * Property 1: Remediate vendor validation
 *
 * For any non-empty string of 1–200 characters (trimmed, with at least one
 * non-whitespace character), submitting it as the vendor field with workflow_type
 * "Remediate" to the queue API SHALL be accepted; and for any empty,
 * whitespace-only, or >200 character vendor string, the request SHALL be
 * rejected with a 400 status.
 *
 * **Validates: Requirements 1.2, 1.3**
 */

const fc = require('fast-check');

// ---------------------------------------------------------------------------
// Replicate the pure validation logic from ivantiTodoQueue.js
// ---------------------------------------------------------------------------

const VALID_WORKFLOW_TYPES = ['FP', 'Archer', 'CARD', 'GRANITE', 'DECOM', 'Remediate'];
const INVENTORY_TYPES = ['CARD', 'GRANITE', 'DECOM'];

function isValidVendor(vendor) {
    if (typeof vendor !== 'string') return false;
    const trimmed = vendor.trim();
    return trimmed.length > 0 && trimmed.length <= 200;
}

/**
 * Simulates the validation logic for the batch/single add endpoints.
 * Returns { accepted: boolean, status: number } mirroring the route behavior.
 */
function validateRemediateRequest(vendor) {
    const workflow_type = 'Remediate';

    if (!VALID_WORKFLOW_TYPES.includes(workflow_type)) {
        return { accepted: false, status: 400 };
    }

    // Remediate is NOT in INVENTORY_TYPES, so vendor is required
    if (!INVENTORY_TYPES.includes(workflow_type)) {
        if (!isValidVendor(vendor)) {
            return { accepted: false, status: 400 };
        }
    }

    return { accepted: true, status: 201 };
}

// ---------------------------------------------------------------------------
// Arbitraries
// ---------------------------------------------------------------------------

// Valid vendor: 1–200 chars trimmed, at least one non-whitespace char
const arbValidVendor = fc.string({ minLength: 1, maxLength: 200 }).filter(s => {
    const trimmed = s.trim();
    return trimmed.length > 0 && trimmed.length <= 200;
});

// Invalid vendor: empty string
const arbEmptyVendor = fc.constant('');

// Invalid vendor: whitespace-only strings
const arbWhitespaceOnlyVendor = fc.array(
    fc.constantFrom(' ', '\t', '\n', '\r'),
    { minLength: 1, maxLength: 50 }
).map(arr => arr.join(''));

// Invalid vendor: strings > 200 chars when trimmed
const arbOverlengthVendor = fc.string({ minLength: 201, maxLength: 400 }).filter(s => {
    return s.trim().length > 200;
});

// ---------------------------------------------------------------------------
// Property 1: Remediate vendor validation
// ---------------------------------------------------------------------------
describe('Feature: ivanti-queue-remediation, Property 1: Remediate vendor validation', () => {
    it('accepts any non-empty vendor string of 1–200 trimmed characters with at least one non-whitespace', () => {
        fc.assert(
            fc.property(arbValidVendor, (vendor) => {
                const result = validateRemediateRequest(vendor);
                expect(result.accepted).toBe(true);
                expect(result.status).toBe(201);
            }),
            { numRuns: 100 }
        );
    });

    it('rejects empty string as vendor for Remediate workflow', () => {
        fc.assert(
            fc.property(arbEmptyVendor, (vendor) => {
                const result = validateRemediateRequest(vendor);
                expect(result.accepted).toBe(false);
                expect(result.status).toBe(400);
            }),
            { numRuns: 10 }
        );
    });

    it('rejects whitespace-only strings as vendor for Remediate workflow', () => {
        fc.assert(
            fc.property(arbWhitespaceOnlyVendor, (vendor) => {
                const result = validateRemediateRequest(vendor);
                expect(result.accepted).toBe(false);
                expect(result.status).toBe(400);
            }),
            { numRuns: 100 }
        );
    });

    it('rejects vendor strings exceeding 200 characters when trimmed', () => {
        fc.assert(
            fc.property(arbOverlengthVendor, (vendor) => {
                const result = validateRemediateRequest(vendor);
                expect(result.accepted).toBe(false);
                expect(result.status).toBe(400);
            }),
            { numRuns: 100 }
        );
    });

    it('rejects non-string vendor values (undefined, null, number)', () => {
        const arbNonString = fc.oneof(
            fc.constant(undefined),
            fc.constant(null),
            fc.integer(),
            fc.boolean()
        );

        fc.assert(
            fc.property(arbNonString, (vendor) => {
                const result = validateRemediateRequest(vendor);
                expect(result.accepted).toBe(false);
                expect(result.status).toBe(400);
            }),
            { numRuns: 100 }
        );
    });
});
