import { MockProxy, mock } from 'jest-mock-extended';
import { Goal } from '../../../../src/api/modules/goals/business/models/goal';
import { GoalCycle } from '../../../../src/api/modules/goals/business/models/goalCycle';
import { GoalWeight } from '../../../../src/api/modules/goals/business/models/goalWeight';
import { GoalCyclesService } from '../../../../src/api/modules/goals/business/services/GoalCyclesService';
import { GoalFormulaChainsService } from '../../../../src/api/modules/goals/business/services/goalFormulaChainsService';
import { GoalsService } from '../../../../src/api/modules/goals/business/services/GoalsService';
import { PerformanceReviewGoalsAdapter } from '../../../../src/api/modules/performanceReviews/infrastructure/adapters/performanceReviewGoalsAdapter';
import { fakePositiveInteger } from '../../../common/common';
import { checkMockCallsCount } from '../../../common/mock/mockHelpers';
import { generateRandomGoal, generateRandomGoalCycle, generateRandomGoalWeight } from '../../goals/common';

let goalsService: MockProxy<GoalsService>;
let goalCyclesService: MockProxy<GoalCyclesService>;
let goalFormulaChainService: MockProxy<GoalFormulaChainsService>;
let goalsAdapter: PerformanceReviewGoalsAdapter;

describe('PerformanceReviewGoalsAdapter', () => {
    beforeEach(() => {
        goalsService = mock<GoalsService>();
        goalCyclesService = mock<GoalCyclesService>();
        goalsAdapter = new PerformanceReviewGoalsAdapter(goalsService, goalCyclesService, goalFormulaChainService);
    });

    describe('getGoalsOfOwnerInCycle', () => {
        it('should get goals of owner in cycle', async () => {
            const goal = generateRandomGoal();
            goalsService.getGoalsOfOwnerInCycle.mockResolvedValueOnce([goal]);

            const result = await goalsAdapter.getGoalsOfOwnerInCycle(fakePositiveInteger(), fakePositiveInteger());

            expect(result).not.toBeNull();
            expect(result).toHaveLength(1);
            expect(result[0]).toBeInstanceOf(Goal);
            expect(result[0]).toBe(goal);

            checkMockCallsCount(goalsService.getGoalsOfOwnerInCycle, 1);
        });
    });

    describe('getGoalCycleByPk', () => {
        it('should get cycle', async () => {
            const goalCycle = generateRandomGoalCycle();
            goalCyclesService.findCycleByPk.mockResolvedValueOnce(goalCycle);

            const result = await goalsAdapter.getGoalCycleByPk(fakePositiveInteger(), fakePositiveInteger());

            expect(result).not.toBeNull();
            expect(result).toBeInstanceOf(GoalCycle);
            expect(result).toBe(goalCycle);

            checkMockCallsCount(goalCyclesService.findCycleByPk, 1);
        });
    });

    describe('getGoalsWeightForOwnerInCycle', () => {
        it('should get goal weights for owner in cycle', async () => {
            const goalCycleId = fakePositiveInteger();
            const ownerId = fakePositiveInteger();
            const goalWeight = generateRandomGoalWeight(goalCycleId, ownerId, fakePositiveInteger());
            goalCyclesService.getGoalsWeightForOwnerInCycle.mockResolvedValueOnce([goalWeight]);

            const result = await goalsAdapter.getGoalsWeightForOwnerInCycle(goalCycleId, ownerId);

            expect(result).not.toBeNull();
            expect(result).toHaveLength(1);
            expect(result[0]).toBeInstanceOf(GoalWeight);
            expect(result[0]).toBe(goalWeight);

            checkMockCallsCount(goalCyclesService.getGoalsWeightForOwnerInCycle, 1);
        });
    });
});
