import { faker } from '@faker-js/faker/locale/en_US';
import { PerformanceReviewEvaluationTypes } from '../../../../src/api/modules/performanceReviews/business/types/performanceReviewEvaluationTypes';
import { SubordinateReviewConfigVC, UpdatePerformanceReviewFormTemplateVC } from '../../../../src/api/modules/performanceReviews/presentation/validationClasses/updatePerformanceReviewFormTemplateVC';
import { fakePositiveInteger } from '../../../common/common';
import { getValidationClass } from '../../../common/serializationClasses/serializationClassesHelper';
import { generateRandomFormReviewConfig } from '../common';

describe('UpdatePerformanceReviewFormTemplateVC', () => {
    it(`should pass validation if the user sends no config`, () => {
        const { errors, output } = getValidationClass(
            {
                templateId: fakePositiveInteger(),
            },
            UpdatePerformanceReviewFormTemplateVC,
        );

        expect(errors).toHaveLength(0);
        expect(output.configDetails).toBeNull();
    });

    it(`should pass validation if the user sends null config details`, () => {
        const { errors } = getValidationClass(
            {
                configDetails: null,
                templateId: fakePositiveInteger(),
            },
            UpdatePerformanceReviewFormTemplateVC,
        );

        expect(errors).toHaveLength(0);
    });

    it(`should pass validation if the user sends config details`, () => {
        const typesWithConfig = Object.values(PerformanceReviewEvaluationTypes).filter(
            (t) => t !== PerformanceReviewEvaluationTypes.CALIBRATION_REVIEW,
        );
        const configDetails = generateRandomFormReviewConfig(faker.helpers.arrayElement(typesWithConfig));
        const { errors } = getValidationClass(
            {
                configDetails,
                templateId: fakePositiveInteger(),
            },
            UpdatePerformanceReviewFormTemplateVC,
        );

        expect(errors).toHaveLength(0);
    });

    it(`should validate correctly if the user sends null template id`, () => {
        const configDetails = generateRandomFormReviewConfig();
        const { errors } = getValidationClass(
            {
                configDetails,
                templateId: null,
            },
            UpdatePerformanceReviewFormTemplateVC,
        );

        const containsTemplateIdError = JSON.stringify(errors).includes('templateId');

        expect(containsTemplateIdError).toBeTrue();
    });

    it(`should validate correctly if the user sends empty template id`, () => {
        const configDetails = generateRandomFormReviewConfig();
        const { errors } = getValidationClass(
            {
                configDetails,
            },
            UpdatePerformanceReviewFormTemplateVC,
        );

        const containsTemplateIdError = JSON.stringify(errors).includes('templateId');

        expect(containsTemplateIdError).toBeTrue();
    });

    it(`should validate correctly if the user sends zero template id`, () => {
        const configDetails = generateRandomFormReviewConfig();
        const { errors } = getValidationClass(
            {
                configDetails,
                templateId: 0,
            },
            UpdatePerformanceReviewFormTemplateVC,
        );

        const containsTemplateIdError = JSON.stringify(errors).includes('templateId');
        expect(containsTemplateIdError).toBeTrue();
    });

    it(`should validate correctly if the user sends invalid config details format`, () => {
        const { errors } = getValidationClass(
            {
                configDetails: { invalidField: 'invalid' },
                templateId: fakePositiveInteger(),
            },
            UpdatePerformanceReviewFormTemplateVC,
        );

        expect(errors.length).toBeGreaterThan(0);
    });

    it('should validate BossReviewConfig with invalid date format', () => {
        const { errors } = getValidationClass(
            {
                templateId: fakePositiveInteger(),
                configDetails: {
                    type: PerformanceReviewEvaluationTypes.BOSS_REVIEW,
                    anonymousAnswers: true,
                    reviewerLimitByHiringDate: 'invalid-date',
                },
            },
            UpdatePerformanceReviewFormTemplateVC,
        );

        expect(errors.length).toBeGreaterThan(0);
        expect(JSON.stringify(errors)).toContain('reviewerLimitByHiringDate');
    });

    it('should validate PeerReviewConfig with invalid selection mode', () => {
        const { errors } = getValidationClass(
            {
                templateId: fakePositiveInteger(),
                configDetails: {
                    type: PerformanceReviewEvaluationTypes.PEER_REVIEW,
                    anonymousAnswers: true,
                    selectionMode: 'INVALID_MODE',
                },
            },
            UpdatePerformanceReviewFormTemplateVC,
        );

        expect(errors.length).toBeGreaterThan(0);
        expect(JSON.stringify(errors)).toContain('selectionMode');
    });

    it('should validate SubordinateReviewConfig with missing required fields', () => {
        const { errors } = getValidationClass(
            {
                templateId: fakePositiveInteger(),
                configDetails: {
                    type: PerformanceReviewEvaluationTypes.SUBORDINATE_REVIEW,
                    canBeShared: true,
                    // missing reviewsVisibleAfterFinishedReviewCycle
                },
            },
            UpdatePerformanceReviewFormTemplateVC,
        );

        expect(errors.length).toBeGreaterThan(0);
        expect(JSON.stringify(errors)).toContain('reviewsVisibleAfterFinishedReviewCycle');
    });

    it('should pass validation when SubordinateReviewConfig includes withCalibration true', () => {
        const { errors, output } = getValidationClass(
            {
                templateId: fakePositiveInteger(),
                configDetails: {
                    type: PerformanceReviewEvaluationTypes.SUBORDINATE_REVIEW,
                    canBeShared: true,
                    reviewsVisibleAfterFinishedReviewCycle: true,
                    canBeSharedBeforeCycleFinish: false,
                    withCalibration: true,
                },
            },
            UpdatePerformanceReviewFormTemplateVC,
        );

        expect(errors).toHaveLength(0);
        const configDetails = output!.configDetails as SubordinateReviewConfigVC;
        expect(configDetails.withCalibration).toBe(true);
    });

    it('should default withCalibration to false when omitted in SubordinateReviewConfig', () => {
        const { errors, output } = getValidationClass(
            {
                templateId: fakePositiveInteger(),
                configDetails: {
                    type: PerformanceReviewEvaluationTypes.SUBORDINATE_REVIEW,
                    canBeShared: true,
                    reviewsVisibleAfterFinishedReviewCycle: true,
                    canBeSharedBeforeCycleFinish: false,
                },
            },
            UpdatePerformanceReviewFormTemplateVC,
        );

        expect(errors).toHaveLength(0);
        const configDetails = output!.configDetails as SubordinateReviewConfigVC;
        expect(configDetails.withCalibration).toBe(false);
    });

    it('should validate config type is required', () => {
        const { errors } = getValidationClass(
            {
                templateId: fakePositiveInteger(),
                configDetails: {
                    anonymousAnswers: true,
                    // missing type field
                },
            },
            UpdatePerformanceReviewFormTemplateVC,
        );

        expect(errors.length).toBeGreaterThan(0);
    });
});
