class CompetitionSetupTemplateServiceImpl implements CompetitionSetupTemplateService {

    @Override
    public ServiceResult<Competition> initializeCompetitionByCompetitionTemplate(Long competitionId, Long competitionTypeId) {
        Optional<CompetitionType> competitionType = competitionTypeRepository.findById(competitionTypeId);

        if (!competitionType.isPresent()) {
            return serviceFailure(new Error(COMPETITION_NOT_EDITABLE));
        }

        Optional<Competition> competitionOptional = competitionRepository.findById(competitionId);
        if (!competitionOptional.isPresent() || competitionIsNotInSetupState(competitionOptional.get())) {
            return serviceFailure(new Error(COMPETITION_NOT_EDITABLE));
        }

        Competition competition = competitionOptional.get();

        competition.setCompetitionType(competitionType.get());
        setDefaultAssessorPayAndCountAndAverageAssessorScore(competition);
        setDefaultOrganisationConfig(competition);
        setDefaultApplicationConfig(competition);

        setDefaultProjectDocuments(competition);

        competitionInitialiser.initialiseFinanceTypes(competition);
        competitionInitialiser.initialiseProjectSetupColumns(competition);

        CompetitionTemplate template = templates.get(competition.getCompetitionTypeEnum());

        List<SectionBuilder> sectionBuilders = template.sections();

        overrideTermsAndConditionsTerminologyForInvestorPartnerships(competition.getFundingType(), sectionBuilders);

        competition.setSections(sectionBuilders.stream().map(SectionBuilder::build).collect(Collectors.toList()));

        template.copyTemplatePropertiesToCompetition(competition);
        overrideTermsAndConditionsForNonGrantCompetitions(competition);

        questionPriorityOrderService.persistAndPrioritiseSections(competition, competition.getSections(), null);
        return serviceSuccess(competitionRepository.save(competition));
    }

}