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.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 a given Product-Unit is valid.<br>
 * It checks weather:
 * <ul>
 * <li>The provided unit is parseable to a numeric value</li>
 * <li>The product ID provided points to a product</li>
 * <li>The product has a matching unit number</li>
 * </ul>
 */
@Slf4j
public class ProductUnitChecker implements IChecker {

    private final ProductUnit productUnit;

    /**
     * Simple constructor.
     *
     * @param productUnit the {@link ProductUnit} to be checked.
     */
    public ProductUnitChecker(final ProductUnit productUnit) {
        this.productUnit = productUnit;
    }

    @Override
    public void check(final TcSession session) throws InvalidUserInputException {
        String productID = productUnit.getProductID();
        UserInputErrorEnum productAndUnitDoesNotExist = getErrorMessage();
        try {
            // Parse user input
            productUnit.parseUserUnit();
            int userUnit = productUnit.getUnit();

            // Get existing units in Database
            List<String> units = new ObjectInfoLoader(session).getUnitsOfProduct(productID);

            // check if the user input Unit exists in the list returned by Tc
            for (String existingTcUnitStr : units) {
                int tcUnit = parseTeamcenterUnit(existingTcUnitStr);
                if (userUnit == tcUnit) {
                    // Found a matching unit, test passed
                    return;
                }
            }
            // The check has failed if it gets here
            log.error(productAndUnitDoesNotExist.getMsgEn());
            log.error("Existing units for this product ({}): {}", productID, units);
            throw new InvalidUserInputException(productAndUnitDoesNotExist);
        } catch (NotFoundException e) {
            throw new InvalidUserInputException(getErrorMessage(), e);

        }
    }

    protected UserInputErrorEnum getErrorMessage() {
        return UserInputErrorEnum.PRODUCT_AND_UNIT_DOES_NOT_EXIST;
    }

    private int parseTeamcenterUnit(final String tcUnitStr) throws InvalidUserInputException {
        try {
            return Integer.parseInt(tcUnitStr);
        } catch (NumberFormatException e) {
            log.error("Teamcenter returned a non-parseable unit String : \"" + tcUnitStr + "\"", e);
            throw new InvalidUserInputException(UserInputErrorEnum.INTERNAL_ERROR, e);
        }
    }

}
