const admin = require('firebase-admin');
const usdaController = require('../usda.controller');
const {getNutritionFeedback} = require('./getNutritionFeedback');
const {getScoreFeedback} = require('./getScoreFeedback');

const additives = require('./additives.json');
const firstIngredients = require('./first_ingredient.json');

const UNITS = {
    Grams: 'g',
    Tablespoon: 'tbsp',
    TeaSpoon: 'tsp',
    Ounces: 'oz',
    Kilogram: 'kg',
    Pounds: 'lbs',
};

const NUTRIENTS = {
    Calories: 1008,
    Sugar: 1235,
    Sodium: 1093,
    Fat: 1004,
    TransFat: 1257,
    SaturatedFat: 1258,
};

exports.calculateScore = async (snack_id, portion, unit) => {

    let _snack = null;
    let _portion = portion || 100;
    let _unit = unit || 'grams';

    let _score = {
        calories: 0,
        firstIngredient: 0,
        processed: 0,
        saturatedFat: 0,
        sodium: 0,
        sugar: 0,
        total: 0,
        totalFat: 0,
        transFat: 0,
    };

    function getSnackIngredients() {
        return _snack.data.ingredients;
    }

    function getSnackFirstIngredient() {
        return _snack.data.ingredients[0];
    }

    async function fetchSnack(snack_id) {

        const snack = await usdaController.getUSDASnackById(snack_id);
        const splitCSVRegex = /,((?!\d))/g;

        if (snack && snack.data && snack.data.ingredients) {
            snack.data.ingredients = snack.data.ingredients
                .toLowerCase()
                .split(splitCSVRegex)
                .map(item => item.replace('ingredients: ', '')
                                .replace('raising agents', '')
                                .replace('(', '')
                                .replace(')', '')
                                .replace('.', '')
                                .trim()
                );
        }

        _snack = snack;

    }

    function calculateProcessedScore() {

        const total = additives.reduce((total, additive) => {
            if (getSnackIngredients().includes(additive.name.toLowerCase())) {
                total++;
            }
            return total;
        }, 0);

        if (total <= 0) {
            _score.processed = 1;
        } else if (total === 1) {
            _score.processed = 0.5;
        } else if (total <= 3) {
            _score.processed = 0;
        } else if (total <= 5) {
            _score.processed = -0.5;
        } else if (total > 5) {
            _score.processed = -1;
        }

    }

    function calculateFirstIngredientScore() {

        let category = 'other';
        let firstIngredient = getSnackFirstIngredient();

        if (!firstIngredient) {
            _score.firstIngredient = 2;
            return;
        }

        firstIngredients.forEach(ingredient => {
            if (firstIngredient.indexOf(ingredient.name) !== -1) {
                category = ingredient.category;
            }
        });

        switch (category) {
            case 'dairy':
            case 'proteins-nut':
            case 'whole grains':
            case 'vegetables':
            case 'fruits':
            case 'proteins':
                _score.firstIngredient = 2;
                break;
            case 'other':
            case 'none':
                _score.firstIngredient = 0;
                break;
            default:
                _score.firstIngredient = 5;
        }

    }

    function calculateNutrients() {

        const nutrientsList = _snack.data.foodNutrients;
        const amounts = {};

        for (let i = 0; i < nutrientsList.length; i++) {
            const nutrient_id = nutrientsList[i].nutrient.id;
            amounts[nutrient_id] = nutrientsList[i].amount;
        }

        calculateCalories(amounts[NUTRIENTS.Calories]);
        calculateSugar(amounts[NUTRIENTS.Sugar]);
        calculateSodium(amounts[NUTRIENTS.Sodium]);
        calculateFat(amounts[NUTRIENTS.Fat]);
        calculateTransFat(amounts[NUTRIENTS.TransFat]);
        calculateSaturatedFat(amounts[NUTRIENTS.SaturatedFat]);

    }

    function calculateCalories(caloriesAmount = 0) {

        const ratio = calculateRatio();
        const calories = ratio * caloriesAmount;

        if (calories >= 1.0 && calories <= 50) {
            _score.calories = 2;
        } else if (calories >= 50.1 && calories <= 100) {
            _score.calories = 1.5;
        } else if (calories >= 100.1 && calories <= 150) {
            _score.calories = 1;
        } else if (calories >= 150.1 && calories <= 200) {
            _score.calories = 0.5;
        } else if (calories >= 200.1) {
            _score.calories = 0;
        }

    }

    function calculateSugar(sugarAmount = 0) {

        const ratio = calculateRatio();

        _score.sugar = ((sugarAmount * ratio) / _portion) * 100;

        if (_score.sugar >= 0 && _score.sugar <= 14.9) {
            _score.sugar = 2;
        } else if (_score.sugar >= 15 && _score.sugar <= 19.9) {
            _score.sugar = 1.5;
        } else if (_score.sugar >= 20 && _score.sugar <= 24.9) {
            _score.sugar = 1;
        } else if (_score.sugar >= 25 && _score.sugar <= 35) {
            _score.sugar = 0.5;
        } else if (_score.sugar >= 35.1) {
            _score.sugar = 0;
        }

    }

    function calculateSodium(sodiumAmount = 0) {

        const ratio = calculateRatio();

        _score.sodium = ratio * sodiumAmount;

        if (_score.sodium >= 0 && _score.sodium <= 140) {
            _score.sodium = 1;
        } else if (_score.sodium >= 140.1 && _score.sodium <= 170) {
            _score.sodium = 0.5;
        } else if (_score.sodium >= 170.1 && _score.sodium <= 200) {
            _score.sodium = 0.25;
        } else if (_score.sodium >= 200.1) {
            _score.sodium = 0;
        }

    }

    function calculateFat(fatAmount = 0) {

        const ratio = calculateRatio();

        if (_score.calories !== 0) {
            _score.totalFat = ((fatAmount * ratio * 9) / _score.calories) * 100;
        } else {
            _score.totalFat = 0;
        }

        if (_score.totalFat >= 0 && _score.totalFat <= 20) {
            _score.totalFat = 1;
        } else if (_score.totalFat >= 20.1 && _score.totalFat <= 35) {
            _score.totalFat = 0.5;
        } else if (_score.totalFat >= 35.1) {
            _score.totalFat = 0;
        }

    }

    function calculateTransFat(transFatAmount = 0) {

        const ratio = calculateRatio();

        if (transFatAmount * ratio > 0) {
            _score.transFat = 0;
        } else if (transFatAmount * ratio === 0) {
            _score.transFat = 1;
        }

    }

    function calculateSaturatedFat(saturatedFatAmount = 0) {

        const ratio = calculateRatio();

        if (_score.calories !== 0) {
            _score.satFat = ((saturatedFatAmount * ratio * 9) / _score.calories) * 100;
        } else {
            _score.satFat = 0;
        }

        if (_score.satFat >= 0 && _score.satFat <= 4.9) {
            _score.satFat = 1;
        } else if (_score.satFat >= 5.0 && _score.satFat <= 9.9) {
            _score.satFat = 0.5;
        } else if (_score.satFat >= 10) {
            _score.satFat = 0;
        }

    }

    function calculateRatio() {
        switch (_unit) {
            case UNITS.Kilogram:
                return _portion * 1000;
            case UNITS.Ounces:
                return _portion * 28.35;
            case UNITS.Tablespoon:
                return _portion * 17.07;
            case UNITS.TeaSpoon:
                return _portion * 5.69;
            case UNITS.Pounds:
                return _portion * 453.6;
            default:
                return _portion / 100;
        }
    }

    function calculateTotalScore() {
        Object.keys(_score).forEach(key => {
            if (key !== 'total') {
                _score.total += _score[key];
            }
        });
    }


    await fetchSnack(snack_id);
    calculateProcessedScore();
    calculateFirstIngredientScore();
    calculateNutrients();
    calculateTotalScore();

    return {
        ..._score,
        scoreFeedback: getScoreFeedback(_score) || '',
        nutritionFeedback: getNutritionFeedback(_score) || ''
    };

};
