package com.capgemini.reports.reports.parameters.checker;

import com.capgemini.framework.teamcenter.authent.TcSession;
import com.capgemini.reports.exceptions.InvalidUserInputException;
import com.capgemini.reports.exceptions.NotFoundException;
import com.capgemini.reports.exceptions.UserInputErrorEnum;
import com.capgemini.reports.reports.parameters.Generics;
import com.capgemini.reports.reports.parameters.IChecker;
import com.capgemini.reports.reports.parameters.ProductUnit;
import com.capgemini.reports.teamcenter.ObjectInfoLoader;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * This class checks if a {@link Generics}' Generic and/or GenericAssemb exist under the {@link Generics}' Product-Unit.
 */
@Slf4j
public class GenericUnderProductUnitChecker implements IChecker {

    private final Generics generics;

    /**
     * Simple Constructor.
     *
     * @param generic the {@link Generics}
     */
    public GenericUnderProductUnitChecker(final Generics generic) {
        this.generics = generic;
    }

    @Override
    public void check(final TcSession session) throws InvalidUserInputException {
        switch (generics.getType()) {
            case GENERIC:
                genericExists(session);
                break;
            case GENERIC_ASSEMB:
                genericAssembExists(session);
                break;
            case ONLY_PRODUCT:
                break;
            default:
                log.error("Unsupported Enum value, defaulting to ONLY_PRODUCT");
                break;
        }
    }

    /**
     * Checks the generic ID.
     */
    private boolean genericExists(final TcSession session) throws InvalidUserInputException {
        ProductUnit productUnit = generics.getProductUnit();
        String thisGeneric = generics.getGeneric();
        try {
            List<String> genericsFound = new ObjectInfoLoader(session).getGenericsRevisionOfProduct(productUnit);
            for (String existingGeneric : genericsFound) {
                if (thisGeneric.equals(existingGeneric)) {
                    return true;
                }
            }
            log.error("No Generic found with ID \"{}\" for productUnit={}", thisGeneric, productUnit);
            log.error(" + Existing Generic IDs: {}", genericsFound);
            throw new InvalidUserInputException(getTechnicalErrorMessage());
        } catch (NotFoundException e) {
            throw new InvalidUserInputException(getTechnicalErrorMessage(), e);
        }
    }

    private UserInputErrorEnum getTechnicalErrorMessage() {
        return UserInputErrorEnum.PRODUCT_UNIT_GENERIC_INVALID;
    }

    /**
     * Checks the generic Assemb ID.
     */
    private boolean genericAssembExists(final TcSession session) throws InvalidUserInputException {
        ProductUnit productUnit = generics.getProductUnit();
        String genericAssemb = generics.getGenericAssemb();
        try {
            List<String> genericsAssemb = new ObjectInfoLoader(session).getGenericsAssembliesRevisionOfProduct(productUnit);
            for (String existingGenericAssemb : genericsAssemb) {
                if (genericAssemb.equals(existingGenericAssemb)) {
                    return true;
                }
            }
            log.error("No Generic Assemb found with ID \"{}\" for productUnit={}", genericAssemb, productUnit);
            log.error(" + Existing GenericAssemb IDs: {}", genericsAssemb);
            throw new InvalidUserInputException(getAssemblyErrorMessage());
        } catch (NotFoundException e) {
            throw new InvalidUserInputException(getAssemblyErrorMessage(), e);
        }
    }

    private UserInputErrorEnum getAssemblyErrorMessage() {
        return UserInputErrorEnum.PRODUCT_UNIT_GENERIC_ASSEMB_INVALID;
    }
}
