import {
  Component,
  EventEmitter,
  Input,
  OnChanges,
  Output,
  SimpleChanges,
} from '@angular/core';

import {
  Nutrient,
  NutrientQuantity,
  NutrientUnit,
} from 'src/app/shared/interfaces/services/api-fit/response/nutrient.interface';
import { Ingredient } from '../../interfaces/services/api-fit/response/ingredient.interface';
import { NutrientsService } from '../../services/nutrients/nutrients.service';

export interface NutritionalInformation extends Nutrient {
  quantity: NutrientQuantity;
  vd: string;
}

@Component({
  selector: 'app-nutrition-table',
  templateUrl: './nutrition-table.component.html',
  styleUrls: ['./nutrition-table.component.scss'],
})
export class NutritionTableComponent implements OnChanges {
  @Input() ingredients: Ingredient[] = [];
  @Input() servings = 1;
  @Input() showOnlyMacro = false;
  @Input() maxResults = 0;
  @Input() canShowAll = true;
  @Input() orderType: 'none' | 'asc' | 'desc' = 'desc';

  showingAll = false;

  @Output() onGenerateTable = new EventEmitter<NutritionalInformation[]>();

  nutritionalTable: NutritionalInformation[] = [];
  energyTotal = 0;

  constructor(private nutrientsService: NutrientsService) {}

  ngOnChanges(changes: SimpleChanges): void {
    this.resetTable();

    if (
      changes['ingredients']?.currentValue ||
      changes['servings']?.currentValue
    ) {
      this.createNutritionalTable();
    }
  }

  resetTable() {
    this.nutritionalTable = [];
    this.energyTotal = 0;
  }

  createNutritionalTable() {
    const macroNutrients = [
      'carboidrato',
      'proteína',
      'fibra alimentar',
      'lipídeos',
    ];

    const quantifiedNutrients = this.nutrientsService.sumNutrients(
      this.ingredients,
    );

    quantifiedNutrients.forEach((n) => {
      if (n.name.toLowerCase() === 'umidade') return;

      if (this.showOnlyMacro) {
        if (!macroNutrients.includes(n.name.toLowerCase())) return;
      }

      const quantity = (n.quantity as number) / this.servings;
      const referencedNutrient = this.nutrientsService.calculateVD(n, quantity);

      const vd = referencedNutrient.vd as number;

      this.nutritionalTable.push({
        ...referencedNutrient,
        quantity: isNaN(quantity) ? n.quantityPer100 : Math.round(quantity),
        vd: isNaN(vd) ? vd.toString() : `${Math.round(vd)}%`,
      });
    });

    if (this.orderType !== 'none') {
      const returnNumber = this.orderType === 'asc' ? 1 : -1;

      this.nutritionalTable.sort((nutrientA, nutrientB) => {
        if (nutrientA.unit === nutrientB.unit) {
          if (nutrientA.quantity === nutrientB.quantity) return 0;
          if (nutrientA.quantity > nutrientB.quantity) return returnNumber;
          return returnNumber * -1;
        }

        if (nutrientA.unit !== nutrientB.unit) {
          const unitsMultiplier: Record<NutrientUnit, number> = {
            percents: 10000,
            g: 1,
            mg: -1000,
            mcg: -1000000,
          };

          if (unitsMultiplier[nutrientA.unit] === unitsMultiplier[nutrientB.unit]) return 0;
          if (unitsMultiplier[nutrientA.unit] > unitsMultiplier[nutrientB.unit]) return returnNumber;
          return (returnNumber * -1);
        }
        
        return 0;
      });
    }

    this.energyTotal = Math.round(
      this.nutrientsService.calculateTotalEnergy(this.ingredients) /
        this.servings,
    );

    this.onGenerateTable.emit(this.nutritionalTable);
  }

  getNutrientUnit(unit: Nutrient['unit']): string {
    return this.nutrientsService.getUnit(unit);
  }
}
