import partTypeStrings from '@/constants/part-type-strings';
import damageLocationsSelected from '@/constants/damage-locations-selected';
import packageNames from '@/constants/package-names';

export function findLineItemsWithPartType(typeToFind, itemsToSearch) {
    return itemsToSearch
        ?.filter((lineItem) => lineItem.partType.toUpperCase() === typeToFind.toUpperCase());
}

export function containsLineItemWithPartType(typeToFind, itemsToSearch) {
    const partTypeMatches = findLineItemsWithPartType(typeToFind, itemsToSearch);
    return !!partTypeMatches?.length;
}

export function getVapsLineItems(availableLineItems, vapTypes) {
    const lineItems = [];

    for (let i = 0; i < vapTypes.length; i++) {
        lineItems.push(...findLineItemsWithPartType(vapTypes[i], availableLineItems));
    }

    return lineItems;
}

export function containsGlassPieceWithLocation(locationToFind, glassPiecesToSearch) {
    const glassLocationMatches = glassPiecesToSearch?.filter((glassPiece) =>
        glassPiece.glassLocation.toUpperCase() === locationToFind.toUpperCase());

    return !!glassLocationMatches?.length;
}

export function shouldFrontWipersBeAvailable(
    glassToReplace,
    availableLineItems,
    isRepair,
    targetTier
) {
    const frontWiperIsAvailable = containsLineItemWithPartType(
        partTypeStrings.FRONT_WIPER,
        availableLineItems
    );

    const isFrontWindshieldTask =
        isRepair || containsGlassPieceWithLocation(damageLocationsSelected.WINDSHIELD, glassToReplace);
    switch (targetTier) {
        case packageNames.TIER_TWO:
            return frontWiperIsAvailable && isFrontWindshieldTask;
        case packageNames.TIER_THREE:
            return frontWiperIsAvailable;
        default:
            return false;
    }
}

export function shouldRearWipersBeAvailable(
    glassToReplace,
    availableLineItems,
    targetTier
) {
    const rearWiperIsAvailable = containsLineItemWithPartType(
        partTypeStrings.REAR_WIPER,
        availableLineItems
    );
    const frontWiperIsAvailable = containsLineItemWithPartType(
        partTypeStrings.FRONT_WIPER,
        availableLineItems
    );
    const isRearWindshieldTask = containsGlassPieceWithLocation(
        damageLocationsSelected.REAR,
        glassToReplace
    );

    switch (targetTier) {
        case packageNames.TIER_TWO:
            return rearWiperIsAvailable && isRearWindshieldTask;
        case packageNames.TIER_THREE:
            return rearWiperIsAvailable && (isRearWindshieldTask || !frontWiperIsAvailable);
        default:
            return false;
    }
}

export function shouldRainDefenseBeAvailable(
    glassToReplace,
    availableLineItems,
    isRepair,
    targetTier
) {
    const isTierThree = targetTier === packageNames.TIER_THREE;
    const frontWipersInTierTwo = shouldFrontWipersBeAvailable(
        glassToReplace,
        availableLineItems,
        isRepair,
        packageNames.TIER_TWO
    );
    const frontWipersInTierThree = shouldFrontWipersBeAvailable(
        glassToReplace,
        availableLineItems,
        isRepair,
        packageNames.TIER_THREE
    );
    const rearWipersInTierTwo = shouldRearWipersBeAvailable(
        glassToReplace,
        availableLineItems,
        packageNames.TIER_TWO
    );

    return isTierThree
        && !(rearWipersInTierTwo
            && !frontWipersInTierTwo
            && frontWipersInTierThree);
}

export function getPackageContents(glassToReplace, availableLineItems, isRepair, targetTier) {
    const vaps = [];

    if (shouldFrontWipersBeAvailable(glassToReplace, availableLineItems, isRepair, targetTier)) {
        vaps.push(partTypeStrings.FRONT_WIPER);
    }

    if (shouldRearWipersBeAvailable(glassToReplace, availableLineItems, targetTier)) {
        vaps.push(partTypeStrings.REAR_WIPER);
    }

    if (shouldRainDefenseBeAvailable(glassToReplace, availableLineItems, isRepair, targetTier)) {
        vaps.push(partTypeStrings.RAIN_DEFENSE);
    }

    return vaps;
}

export function getAvailablePackages(glassToReplace, availableLineItems, isRepair) {
    const tierOneVaps = getPackageContents(
        glassToReplace,
        availableLineItems,
        isRepair,
        packageNames.TIER_ONE
    );

    const tierTwoVaps = getPackageContents(
        glassToReplace,
        availableLineItems,
        isRepair,
        packageNames.TIER_TWO
    );

    const tierThreeVaps = getPackageContents(
        glassToReplace,
        availableLineItems,
        isRepair,
        packageNames.TIER_THREE
    );

    if (tierTwoVaps.length === 0) {
        return [
            {
                packageName: packageNames.TIER_ONE,
                vapTypes: tierOneVaps
            },
            {
                packageName: packageNames.TIER_THREE,
                vapTypes: tierThreeVaps
            }
        ];
    }
    return [
        {
            packageName: packageNames.TIER_ONE,
            vapTypes: tierOneVaps
        },
        {
            packageName: packageNames.TIER_TWO,
            vapTypes: tierTwoVaps
        },
        {
            packageName: packageNames.TIER_THREE,
            vapTypes: tierThreeVaps
        }
    ];
}

export function getLowestTierForType(glassToReplace, availableLineItems, isRepair, partType) {
    const packages = getAvailablePackages(glassToReplace, availableLineItems, isRepair);
    for (let i = 0; i < packages.length; i++) {
        for (let j = 0; j < packages[i].vapTypes.length; j++) {
            if (packages[i].vapTypes[j].toUpperCase() === partType.toUpperCase()) {
                return packages[i].packageName;
            }
        }
    }

    return packageNames.TIER_ONE;
}

function maxTier(tierA, tierB) {
    if (tierA === packageNames.TIER_THREE || tierB === packageNames.TIER_THREE) {
        return packageNames.TIER_THREE;
    }

    if (tierA === packageNames.TIER_TWO || tierB === packageNames.TIER_TWO) {
        return packageNames.TIER_TWO;
    }

    return packageNames.TIER_ONE;
}

export function getHighestRequiredTier(glassToReplace, availableLineItems, isRepair, vaps) {
    let currentHighestTier = packageNames.TIER_ONE;
    for (let i = 0; i < vaps.length; i++) {
        const lowestTierForItem = getLowestTierForType(
            glassToReplace,
            availableLineItems,
            isRepair,
            vaps[i].partType
        );

        currentHighestTier = maxTier(currentHighestTier, lowestTierForItem);
    }

    return currentHighestTier;
}

export function getHighestFullySatisfiedTier(glassToReplace, availableLineItems, isRepair, vaps) {
    const packages = getAvailablePackages(glassToReplace, availableLineItems, isRepair);
    let highestSatisfiedPackage = packageNames.TIER_ONE;

    for (let i = 0; i < packages.length; i++) {
        let isPackageSatisfied = true;
        for (let j = 0; j < packages[i].vapTypes.length; j++) {
            isPackageSatisfied =
                isPackageSatisfied && containsLineItemWithPartType(packages[i].vapTypes[j], vaps);
        }
        if (isPackageSatisfied) {
            highestSatisfiedPackage = packages[i].packageName;
        }
    }

    return highestSatisfiedPackage;
}
