import { PerformanceReviewTargetUser } from '../../../../src/api/modules/performanceReviews/business/models/performanceReviewTargetUser';
import { PerformanceReviewTargetUserSC } from '../../../../src/api/modules/performanceReviews/presentation/serializationClasses/performanceReviewTargetUserSC';
import { fakePositiveInteger } from '../../../common/common';
import {
    checkPerformanceReviewTargetUserSerialized,
    generatePerformanceReviewFormReviewWithValues,
    generateRandomPerformanceReviewTargetUser,
    generateRandomPerformanceReviewUser,
} from '../common';

describe('PerformanceReviewTargetUserSC', () => {
    let targetUser: PerformanceReviewTargetUser;
    let extraData: { scoreNeedsObfuscation: boolean };

    beforeEach(() => {
        targetUser = generateRandomPerformanceReviewTargetUser(fakePositiveInteger(), fakePositiveInteger(), fakePositiveInteger());
        extraData = { scoreNeedsObfuscation: false };
    });

    it('should serialize review form without users', () => {
        const targetUserSerialized = new PerformanceReviewTargetUserSC().serialize(targetUser, extraData);

        expect(targetUserSerialized).not.toBeNull();

        checkPerformanceReviewTargetUserSerialized(targetUser, targetUserSerialized, extraData.scoreNeedsObfuscation);
    });

    it('should serialize review form with user', () => {
        targetUser.user = generateRandomPerformanceReviewUser(targetUser.userId);

        const targetUserSerialized = new PerformanceReviewTargetUserSC().serialize(targetUser, extraData);

        expect(targetUserSerialized).not.toBeNull();

        checkPerformanceReviewTargetUserSerialized(targetUser, targetUserSerialized, extraData.scoreNeedsObfuscation);
    });

    it('should serialize review form with responsible', () => {
        targetUser.responsible = generateRandomPerformanceReviewUser(targetUser.responsibleId as number);

        const targetUserSerialized = new PerformanceReviewTargetUserSC().serialize(targetUser, extraData);

        expect(targetUserSerialized).not.toBeNull();

        checkPerformanceReviewTargetUserSerialized(targetUser, targetUserSerialized, extraData.scoreNeedsObfuscation);
    });

    it('should serialize target user with reviewed form reviews to calculate score', () => {
        const formReviewsCount = fakePositiveInteger({ max: 3, min: 1 });
        const score = fakePositiveInteger();
        targetUser.reviewedFormReviews = Array(formReviewsCount)
            .fill(1)
            .map(() =>
                generatePerformanceReviewFormReviewWithValues(fakePositiveInteger(), targetUser.cycleId, {
                    coreFormAnswerId: fakePositiveInteger(),
                    score,
                }),
            );
        targetUser.score = score;

        const targetUserSerialized = new PerformanceReviewTargetUserSC().serialize(targetUser, extraData);

        expect(targetUserSerialized).not.toBeNull();
        expect(targetUserSerialized.score).not.toBeNull();

        checkPerformanceReviewTargetUserSerialized(targetUser, targetUserSerialized, extraData.scoreNeedsObfuscation);
    });

    it('should serialize target user with reviewed form reviews to calculate score, with obfuscation', () => {
        extraData = { scoreNeedsObfuscation: true };
        const score = fakePositiveInteger();
        const formReviewsCount = fakePositiveInteger({ max: 3, min: 1 });
        targetUser.reviewedFormReviews = Array(formReviewsCount)
            .fill(1)
            .map(() =>
                generatePerformanceReviewFormReviewWithValues(fakePositiveInteger(), targetUser.cycleId, {
                    coreFormAnswerId: fakePositiveInteger(),
                    score,
                }),
            );
        targetUser.score = score;
        const targetUserSerialized = new PerformanceReviewTargetUserSC().serialize(targetUser, extraData);

        expect(targetUserSerialized).not.toBeNull();
        expect(targetUserSerialized.score).toBeNull();

        checkPerformanceReviewTargetUserSerialized(targetUser, targetUserSerialized, extraData.scoreNeedsObfuscation);
    });
});
