import { faker } from '@faker-js/faker/locale/af_ZA';
import { PerformanceReviewReviewer } from '../../../../src/api/modules/performanceReviews/business/models/performanceReviewReviewer';
import { PerformanceReviewUser } from '../../../../src/api/modules/performanceReviews/business/models/performanceReviewUser';
import { PerformanceReviewReviewedStatus } from '../../../../src/api/modules/performanceReviews/business/types/performanceReviewReviewedStatus';
import { PerformanceReviewReviewedSC } from '../../../../src/api/modules/performanceReviews/presentation/serializationClasses/performanceReviewReviewedSC';
import { User } from '../../../../src/api/modules/users/business/models/user';
import { fakePositiveInteger } from '../../../common/common';
import { checkPerformanceReviewReviewedSerialized, generatePerformanceReviewReviewer, generateRandomPerformanceReviewUser } from '../common';

describe('PerformanceReviewReviewedSC', () => {
    let reviewedData: {
        reviewed: PerformanceReviewReviewer | null;
        user: PerformanceReviewUser;
        bosses: User[];
        hasPeerEvaluationType: boolean;
        hasPeerExternalEvaluationType: boolean;
    };

    beforeEach(() => {
        const boss = new User();
        boss.firstName = faker.person.firstName();
        boss.firstName = faker.person.lastName();

        reviewedData = {
            bosses: [boss],
            hasPeerEvaluationType: faker.datatype.boolean(),
            hasPeerExternalEvaluationType: faker.datatype.boolean(),
            reviewed: generatePerformanceReviewReviewer({}),
            user: generateRandomPerformanceReviewUser(fakePositiveInteger()),
        };
    });

    it('should serialize reviewed without boss', () => {
        reviewedData.bosses = [];
        const reviewedSerialized = new PerformanceReviewReviewedSC().serialize(reviewedData);

        expect(reviewedSerialized).not.toBeNull();

        checkPerformanceReviewReviewedSerialized(reviewedData, reviewedSerialized);
    });

    it('should serialize reviewed without reviewed', () => {
        reviewedData.reviewed = null;
        const reviewedSerialized = new PerformanceReviewReviewedSC().serialize(reviewedData);

        expect(reviewedSerialized).not.toBeNull();

        checkPerformanceReviewReviewedSerialized(reviewedData, reviewedSerialized);
    });

    it('should serialize reviewed', () => {
        const reviewedSerialized = new PerformanceReviewReviewedSC().serialize(reviewedData);

        expect(reviewedSerialized).not.toBeNull();

        checkPerformanceReviewReviewedSerialized(reviewedData, reviewedSerialized);
    });

    it('should serialize reviewed with external only and PENDING status', () => {
        reviewedData.hasPeerEvaluationType = false;
        reviewedData.hasPeerExternalEvaluationType = true;
        const reviewed = generatePerformanceReviewReviewer({ externalReviewerCount: 0, reviewerCount: 0 });
        reviewedData.reviewed = reviewed;
        const reviewedSerialized = new PerformanceReviewReviewedSC().serialize(reviewedData);

        expect(reviewedSerialized).not.toBeNull();
        expect(reviewedSerialized.status).toBe(PerformanceReviewReviewedStatus.PENDING);

        checkPerformanceReviewReviewedSerialized(reviewedData, reviewedSerialized);
    });

    it('should serialize reviewed with external only and ASSIGNED status', () => {
        reviewedData.hasPeerEvaluationType = false;
        reviewedData.hasPeerExternalEvaluationType = true;
        const reviewed = generatePerformanceReviewReviewer({ reviewedCount: 0 });
        reviewedData.reviewed = reviewed;
        const reviewedSerialized = new PerformanceReviewReviewedSC().serialize(reviewedData);

        expect(reviewedSerialized).not.toBeNull();
        expect(reviewedSerialized.status).toBe(PerformanceReviewReviewedStatus.ASSIGNED);

        checkPerformanceReviewReviewedSerialized(reviewedData, reviewedSerialized);
    });

    it('should serialize reviewed with internal only and PENDING status', () => {
        reviewedData.hasPeerEvaluationType = true;
        reviewedData.hasPeerExternalEvaluationType = false;
        const reviewed = generatePerformanceReviewReviewer({ externalReviewerCount: 0, reviewerCount: 0 });
        reviewedData.reviewed = reviewed;
        const reviewedSerialized = new PerformanceReviewReviewedSC().serialize(reviewedData);

        expect(reviewedSerialized).not.toBeNull();
        expect(reviewedSerialized.status).toBe(PerformanceReviewReviewedStatus.PENDING);

        checkPerformanceReviewReviewedSerialized(reviewedData, reviewedSerialized);
    });

    it('should serialize reviewed with internal only and ASSIGNED status', () => {
        reviewedData.hasPeerEvaluationType = true;
        reviewedData.hasPeerExternalEvaluationType = false;
        const reviewed = generatePerformanceReviewReviewer({ externalReviewerCount: 0 });
        reviewedData.reviewed = reviewed;
        const reviewedSerialized = new PerformanceReviewReviewedSC().serialize(reviewedData);

        expect(reviewedSerialized).not.toBeNull();
        expect(reviewedSerialized.status).toBe(PerformanceReviewReviewedStatus.ASSIGNED);

        checkPerformanceReviewReviewedSerialized(reviewedData, reviewedSerialized);
    });

    it('should serialize reviewed with both directions and ASSIGNED status', () => {
        reviewedData.hasPeerEvaluationType = true;
        reviewedData.hasPeerExternalEvaluationType = true;
        const reviewedSerialized = new PerformanceReviewReviewedSC().serialize(reviewedData);

        expect(reviewedSerialized).not.toBeNull();
        expect(reviewedSerialized.status).toBe(PerformanceReviewReviewedStatus.ASSIGNED);

        checkPerformanceReviewReviewedSerialized(reviewedData, reviewedSerialized);
    });

    it('should serialize reviewed with both directions and PENDING status', () => {
        reviewedData.hasPeerEvaluationType = true;
        reviewedData.hasPeerExternalEvaluationType = true;
        const reviewed = generatePerformanceReviewReviewer({ externalReviewerCount: 0, reviewerCount: 0 });
        reviewedData.reviewed = reviewed;
        const reviewedSerialized = new PerformanceReviewReviewedSC().serialize(reviewedData);

        expect(reviewedSerialized).not.toBeNull();
        expect(reviewedSerialized.status).toBe(PerformanceReviewReviewedStatus.PENDING);

        checkPerformanceReviewReviewedSerialized(reviewedData, reviewedSerialized);
    });
});
