import { SegmentationType } from '../../../../src/api/modules/audiences/business/constants/segmentationTypes';
import { CreateCalibrationRuleVC } from '../../../../src/api/modules/performanceReviews/presentation/validationClasses/createCalibrationRuleVC';
import { UpdateCalibrationRuleVC } from '../../../../src/api/modules/performanceReviews/presentation/validationClasses/updateCalibrationRuleVC';
import { getValidationClass } from '../../../common/serializationClasses/serializationClassesHelper';

const validInput = {
    calibratorsAudienceQuery: { conditions: [{ type: SegmentationType.USERS, userIds: [1] }] },
    calibratedAudienceQuery: { conditions: [{ type: SegmentationType.USERS, userIds: [2] }] },
};

describe('CreateCalibrationRuleVC', () => {
    it('should accept valid input', () => {
        const { errors } = getValidationClass(validInput, CreateCalibrationRuleVC);
        expect(errors).toBeEmpty();
    });

    it('should reject empty object', () => {
        const { errors } = getValidationClass({}, CreateCalibrationRuleVC);
        expect(errors).toPartiallyContain({ property: 'calibratorsAudienceQuery' });
        expect(errors).toPartiallyContain({ property: 'calibratedAudienceQuery' });
    });

    it('should reject missing calibratorsAudienceQuery', () => {
        const { errors } = getValidationClass({ calibratedAudienceQuery: validInput.calibratedAudienceQuery }, CreateCalibrationRuleVC);
        expect(errors).toPartiallyContain({ property: 'calibratorsAudienceQuery' });
    });

    it('should reject missing calibratedAudienceQuery', () => {
        const { errors } = getValidationClass({ calibratorsAudienceQuery: validInput.calibratorsAudienceQuery }, CreateCalibrationRuleVC);
        expect(errors).toPartiallyContain({ property: 'calibratedAudienceQuery' });
    });

    it('should reject empty conditions array', () => {
        const { errors } = getValidationClass(
            { calibratorsAudienceQuery: { conditions: [] }, calibratedAudienceQuery: validInput.calibratedAudienceQuery },
            CreateCalibrationRuleVC,
        );
        expect(errors).not.toBeEmpty();
    });

    it('should accept USERS type with userIds', () => {
        const { errors } = getValidationClass(
            {
                calibratorsAudienceQuery: { conditions: [{ type: SegmentationType.USERS, userIds: [1, 2, 3] }] },
                calibratedAudienceQuery: { conditions: [{ type: SegmentationType.USERS, userIds: [4] }] },
            },
            CreateCalibrationRuleVC,
        );
        expect(errors).toBeEmpty();
    });

    it('should reject calibratorsAudienceQuery with ALL', () => {
        const { errors } = getValidationClass(
            {
                calibratorsAudienceQuery: { conditions: [{ type: SegmentationType.ALL }] },
                calibratedAudienceQuery: validInput.calibratedAudienceQuery,
            },
            CreateCalibrationRuleVC,
        );
        expect(errors).toPartiallyContain({ property: 'calibratorsAudienceQuery' });
    });

    it('should reject calibratedAudienceQuery with ALL', () => {
        const { errors } = getValidationClass(
            {
                calibratorsAudienceQuery: validInput.calibratorsAudienceQuery,
                calibratedAudienceQuery: { conditions: [{ type: SegmentationType.ALL }] },
            },
            CreateCalibrationRuleVC,
        );
        expect(errors).toPartiallyContain({ property: 'calibratedAudienceQuery' });
    });

    it('should reject ALL nested inside an EXPRESSION condition', () => {
        const { errors } = getValidationClass(
            {
                calibratorsAudienceQuery: {
                    conditions: [
                        {
                            type: SegmentationType.EXPRESSION,
                            operator: 'AND',
                            expressions: [{ type: SegmentationType.ALL }],
                        },
                    ],
                },
                calibratedAudienceQuery: validInput.calibratedAudienceQuery,
            },
            CreateCalibrationRuleVC,
        );
        expect(errors).toPartiallyContain({ property: 'calibratorsAudienceQuery' });
    });
});

describe('UpdateCalibrationRuleVC', () => {
    it('should accept valid input', () => {
        const { errors } = getValidationClass(validInput, UpdateCalibrationRuleVC);
        expect(errors).toBeEmpty();
    });

    it('should reject empty object', () => {
        const { errors } = getValidationClass({}, UpdateCalibrationRuleVC);
        expect(errors).not.toBeEmpty();
    });

    it('should reject ALL in calibratorsAudienceQuery', () => {
        const { errors } = getValidationClass(
            {
                calibratorsAudienceQuery: { conditions: [{ type: SegmentationType.ALL }] },
                calibratedAudienceQuery: validInput.calibratedAudienceQuery,
            },
            UpdateCalibrationRuleVC,
        );
        expect(errors).toPartiallyContain({ property: 'calibratorsAudienceQuery' });
    });
});
