import { Component, OnInit } from '@angular/core';
import { PreventiveOrderWithActivator, PreventiveOrderWithActivatorResponse } from '../../../../interfaces/preventive-order-with-activator.interface';
import { ActivatedRoute } from '@angular/router';
import { EncService } from '../../../../services/enc.service';
import { PreventiveMaintenanceService } from '../../../../services/preventive-maintenance.service';
import { MatDialog } from '@angular/material/dialog';
import { CountersActivatorsService } from '../../../../services/counters-activators.service';
import { ResourcesService } from '../../../../services/resources.service';
import { lastValueFrom } from 'rxjs';
import { UpdateCharacteristicComponent } from './update-characteristic/update-characteristic.component';
import { ActivatorResponse } from '../../../../interfaces/activator.interface';

interface Magnitudes{
  MAGNITUDE: string;
  LABEL: string;
  UNITS: Units[];
}
interface Units{
  UNIT: string,
  LABEL: string,
}
const MAGNITUDES: Magnitudes[] = [
  {MAGNITUDE: 'TEM', LABEL: 'Temperatura', UNITS: [
    {UNIT: 'K', LABEL: '°K - Kelvin'},
    {UNIT: 'C', LABEL: '°C - Celsius'},
    {UNIT: 'F', LABEL: '°F - Fahrenheit'},
  ]},
  {MAGNITUDE: 'TEN', LABEL: 'Tensión', UNITS: [
    {UNIT: 'V', LABEL: 'V - Volts'},
  ]},
  {MAGNITUDE: 'COR', LABEL: 'Corriente', UNITS: [
    {UNIT: 'A', LABEL: 'A - Amperios'},
  ]},
  {MAGNITUDE: 'POT', LABEL: 'Potencia', UNITS: [
    {UNIT: 'W', LABEL: 'W - Watts'},
    {UNIT: 'HP', LABEL: 'HP - Caballos de fuerza'}
  ]},
  {MAGNITUDE: 'FRE', LABEL: 'Frecuencia', UNITS: [
    {UNIT: 'Hz', LABEL: 'Hz - Hertz'},
    {UNIT: 'RPM', LABEL: 'RPM - Revoluciones por minuto'},
  ]},
  {MAGNITUDE: 'VEL', LABEL: 'Velocidad', UNITS: [
    {UNIT: 'm/s', LABEL: 'm/s - Metros por segundo'},
    {UNIT: 'm/h', LABEL: 'm/h - Metros por hora'},
    {UNIT: 'km/h', LABEL: 'km/h - Kilometros por hora'},
  ]},
  {MAGNITUDE: 'DIS', LABEL: 'Distancia', UNITS: [
    {UNIT: 'cm', LABEL: 'cm - Centímetros'},
    {UNIT: 'm', LABEL: 'm - Metros'},
    {UNIT: 'km', LABEL: 'km - Kilometros'},
    {UNIT: 'in', LABEL: 'in - Pulgada'},
    {UNIT: 'ft', LABEL: 'ft - Pies'},
    {UNIT: 'yd', LABEL: 'yd - Yarda'},
  ]}
];
@Component({
    selector: 'app-edit-activator',
    templateUrl: './edit-activator.component.html',
    styleUrl: './edit-activator.component.css',
    standalone: false
})
export class EditActivatorComponent implements OnInit {
  isLoading: boolean;
  hasError: boolean;
  errorStr: string;
  idOrder: number;
  preventiveOrder: PreventiveOrderWithActivator | null;
  activatorConfig: any;

  dayNames = ['Domingos', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábados'];
  MONTHS = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'];
  
  magnitudes: Magnitudes[];

  signs: any = {
    SIN1: "Sobrecalentamiento",
    SIN2: "Rechinido",
    SIN3: "Fundido",
    SIN4: "Vibración",
  };

  datesCols = 4;
  timesCols = 2;
  threeCols = 3;

  constructor(
    private _route: ActivatedRoute,
    private _encService: EncService,
    private _prevMaintService: PreventiveMaintenanceService,
    private _dialog: MatDialog,
    private _countActiService: CountersActivatorsService,
    private _resourcesService: ResourcesService,
  ) {
    this.isLoading = true;
    this.hasError = false;
    this.errorStr = "";
    this.idOrder = 0;
    this.preventiveOrder = null;
    this.magnitudes = MAGNITUDES;

    this.datesCols = window.innerWidth > 1400 ? 4 : window.innerWidth > 900 ? 2 : 1;
    this.timesCols = window.innerWidth > 1045 ? 2 : 1;
    this.threeCols = window.innerWidth > 1280 ? 3 : window.innerWidth > 900 ? 2 : 1;
  }

  ngOnInit(): void {
    this._route.queryParams.subscribe(res => {
      let data = res['data'];
      if(data == undefined || data == null || data == ''){
        this._resourcesService.openSnackBar('No se envió ninguna información.');
        window.history.back();
      }else{
        this.getWorkOrder(data);
      }
    });
  }

  async getWorkOrder(idOrderEnc: string){
    try{
      let idOrderDec = await this._encService.decrypt(idOrderEnc);
      this.idOrder = parseInt(idOrderDec);

      let idUser = localStorage.getItem('idusuario')!;
      let order: PreventiveOrderWithActivatorResponse = await lastValueFrom(this._prevMaintService.getOrderWithActivator(
        idOrderEnc,
        idUser,
        1
      ));
      
      this.hasError = order.error;
      this.errorStr = order.msg;

      if(!this.hasError){
        this.preventiveOrder = order.response;
        this.decodeActivatorConfig(this.preventiveOrder.CONFIGACTIVADOR);
      }

      this.isLoading = false;
    }catch(error: any){
      if(error.error == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else if(error.error.msg == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else{
        this.errorStr = error.error.msg;
      }

      this.hasError = true;
      this.isLoading = false;
    }
  }

  decodeActivatorConfig(activatorConfigStr: string){
    this.activatorConfig = JSON.parse(activatorConfigStr);
  }

  onResize():void{
    this.datesCols = window.innerWidth > 1400 ? 4 : window.innerWidth > 900 ? 2 : 1;
    this.timesCols = window.innerWidth > 1045 ? 2 : 1;
    this.threeCols = window.innerWidth > 1280 ? 3 : window.innerWidth > 900 ? 2 : 1;
  }

  getInstructions(instructionsStr: string): string[]{
    let instructionsArr = JSON.parse(instructionsStr);
    let instructionsFn: string[] = [];

    instructionsArr.forEach((item: any) => {
      instructionsFn.push(item.INSTRUCCION);
    });
    
    return instructionsFn;
  }

  getOrderStartDate(dateStr: string): string{
    let dateTimeArr = dateStr.split(' ');
    let dateArr = dateTimeArr[0].split('-');
    
    if(dateTimeArr[0] == '0001-01-01'){
      return '-';
    }

    return `${parseInt(dateArr[2])} de ${this.MONTHS[parseInt(dateArr[1]) - 1]} del ${dateArr[0]}`;
  }

  openCharacteristicDialog(char: string, value: string | number, type: string | null){
    let dialogRef = this._dialog.open(UpdateCharacteristicComponent, {
      width: '560px',
      maxWidth: '560px',
      disableClose: true,
      data: {
        characteristic: char,
        value: value,
        type: type
      }
    });

    dialogRef.afterClosed().subscribe(res => {
      if(res != null && res != undefined && res != ''){
        this.updateActivatorLocal(res);
      }
    });
  }

  async updateActivatorLocal(newConfig: string){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let newConfigObj = JSON.parse(newConfig);

      if(newConfigObj.characteristic == 'date'){
        let dateArr = newConfigObj.value.split('-');

        dateArr[1] = parseInt(dateArr[1]) < 10 ? `0${dateArr[1]}` : `${dateArr[1]}`;
        dateArr[2] = parseInt(dateArr[2]) < 10 ? `0${dateArr[2]}` : `${dateArr[2]}`;

        let dateStr = dateArr.join('-');
        let activator = JSON.parse(this.preventiveOrder?.CONFIGACTIVADOR!);

        if(newConfigObj.type == 'start'){
          let dateTimeArr = this.preventiveOrder?.FECHAINICIO.split(' ')!;
          dateTimeArr[0] = dateStr;

          this.preventiveOrder!.FECHAINICIO = dateTimeArr.join(' ');

          let actiDateTimeArr = activator.startDate.split('T');
          actiDateTimeArr[0] = dateStr;

          let actiDateTimeStr = actiDateTimeArr.join('T');
          activator.startDate = actiDateTimeStr;
          this.preventiveOrder!.CONFIGACTIVADOR = JSON.stringify(activator);
          this.decodeActivatorConfig(this.preventiveOrder!.CONFIGACTIVADOR);
        }else{
          let endDateArr = newConfigObj.value.split('-');
          let endDate = new Date(parseInt(endDateArr[0]), parseInt(endDateArr[1]) - 1, parseInt(endDateArr[2]));
          let startDate = new Date(this.preventiveOrder!.FECHAINICIO);

          if(endDate.getTime() <= startDate.getTime()){
            this._resourcesService.openSnackBar('La fecha final no puede ser menor a la inicial.');
          }else{
            let endDateTimeArr = this.preventiveOrder!.FECHAFINAL.split(' ');
            let endMonth = parseInt(endDateArr[1]) < 10 ? `0${endDateArr[1]}` : `${endDateArr[1]}`;
            let endDay = parseInt(endDateArr[2]) < 10 ? `0${endDateArr[2]}` : `${endDateArr[2]}`;

            endDateTimeArr[0] = `${endDateArr[0]}-${endMonth}-${endDay}`;

            let endDateTimeStr = endDateTimeArr.join(' ');
            this.preventiveOrder!.FECHAFINAL = endDateTimeStr;
          }
        }
      }else if(newConfigObj.characteristic == 'hour'){
        let timeArr = newConfigObj.value.split(' ');
        let hourArr = timeArr[0].split(':');
        let hour = parseInt(hourArr[0]);
        let activator = JSON.parse(this.preventiveOrder?.CONFIGACTIVADOR!);

        hour = timeArr[1] == 'PM' && hour < 12 ? hour + 12 : hour;
        hourArr[0] = hour < 10 ? `0${hour}` : `${hour}`;

        if(newConfigObj.type == 'start'){
          let dateTimeArr = this.preventiveOrder?.FECHAINICIO.split(' ')!;
          let timeArr = dateTimeArr[1].split(':');

          timeArr[0] = hourArr[0];
          timeArr[1] = hourArr[1];

          let timeStr = timeArr.join(':');
          dateTimeArr[1] = timeStr;

          this.preventiveOrder!.FECHAINICIO = dateTimeArr.join(' ');
          activator.startHour = newConfigObj.value;
          this.preventiveOrder!.CONFIGACTIVADOR = JSON.stringify(activator);
          this.decodeActivatorConfig(this.preventiveOrder!.CONFIGACTIVADOR);
        }else{
          let endDateTimeArr = this.preventiveOrder?.FECHAFINAL.split(' ')!;

          if(endDateTimeArr[0] == '0001-01-01'){
            this._resourcesService.openSnackBar('Para cambiar la hora final primero debe seleccionar una fecha de finalización');
          }else{
            let endHourArr = newConfigObj.value.split(' ');
            let endTimeArr = endHourArr[0].split(':');
            let endHour = parseInt(endTimeArr[0]);

            endHour = endHour < 12 && endHourArr[1] == 'PM' ? endHour + 12 : endHour;
            let endHourStr = endHour < 10 ? `0${endHour}` : `${endHour}`;
            let endTimeStr = `${endHourStr}:${endTimeArr[1]}:00`;

            endDateTimeArr[1] = endTimeStr;
            let endDateTimeStr = endDateTimeArr.join(' ');

            this.preventiveOrder!.FECHAFINAL = endDateTimeStr;
          }
        }
      }else if(newConfigObj.characteristic == 'activator'){
        this.isLoading = true;
        this.hasError = false;
        this.errorStr = '';

        let idActEnc = await this._encService.encrypt(`${newConfigObj.value}`);
        let activator: ActivatorResponse = await lastValueFrom(this._countActiService.getActivator(
          idActEnc,
          idUser,
          1
        ));
        
        this.preventiveOrder!.CONFIGACTIVADOR = activator.response.CONDICIONES as string;
        this.preventiveOrder!.ACTIVADOR = activator.response.IDACTIVADOR as number;
        this.preventiveOrder!.PRIORIDAD = activator.response.PRIORIDAD as string;
        this.preventiveOrder!.TIPOACTIVADOR = activator.response.TIPOACTIVADOR;
        this.decodeActivatorConfig(this.preventiveOrder!.CONFIGACTIVADOR);

        if(this.preventiveOrder?.TIPOACTIVADOR == 'Calendario' || this.preventiveOrder?.TIPOACTIVADOR == 'Sintoma'){
          let actiConf = JSON.parse(activator.response.CONDICIONES as string);
          let dateTimeArr = actiConf.startDate.split('T');
  
          let startHourArr = actiConf.startHour.split(' ');
          let startTimeArr = startHourArr[0].split(':');
          let startHour = parseInt(startTimeArr[0]);
  
          startHour = startHourArr[1] == 'PM' && startHour < 12 ? startHour + 12 : startHour;
          let startHourStr = startHour < 10 ? `0${startHour}` : `${startHour}`;
          let hourStr = `${startHourStr}:${startTimeArr[1]}:00`;
          let dateTimeStr = `${dateTimeArr[0]} ${hourStr}`;
  
          this.preventiveOrder!.FECHAINICIO = dateTimeStr;
  
          if(actiConf.repeat == 'PE'){
            let customRepeat = JSON.parse(actiConf.customRepeat);
            let endsAtArr = customRepeat.endsAt.split('|');
    
            if(endsAtArr[0] == 'O'){
              let endDateArr = endsAtArr[1].split('-');
              let endMonth = parseInt(endDateArr[1]) + 1;
              let endMonthStr = endMonth < 10 ? `0${endMonth}` : `${endMonth}`;
              let endDayStr = parseInt(endDateArr[2]) < 10 ? `0${endDateArr[2]}` : `${endDateArr[2]}`;
              let endDateTimeStr = `${endDateArr[0]}-${endMonthStr}-${endDayStr} 00:00:00`;
    
              this.preventiveOrder!.FECHAFINAL = endDateTimeStr;
            }else{
              this.preventiveOrder!.FECHAFINAL = '0001-01-01 00:00:00';
            }
          }
        }

        this.isLoading = false;
      }else if(newConfigObj.characteristic == 'activatorType'){
        this.openCharacteristicDialog('activator', 0, newConfigObj.value);
      }else if(newConfigObj.characteristic == 'priority'){
        this.preventiveOrder!.PRIORIDAD = newConfigObj.value;
      }else if(newConfigObj.characteristic == 'color'){
        let configActivator = JSON.parse(this.preventiveOrder?.CONFIGACTIVADOR!);
        configActivator.color = newConfigObj.value;

        let configActivatorStr = JSON.stringify(configActivator);
        this.preventiveOrder!.CONFIGACTIVADOR = configActivatorStr;
        this.decodeActivatorConfig(this.preventiveOrder!.CONFIGACTIVADOR);
      }
    }catch(error: any){
      if(error.error == undefined){
        this._resourcesService.openSnackBar('Ocurrió un error inesperado.');
      }else if(error.error.msg == undefined){
        this._resourcesService.openSnackBar('Ocurrió un error inesperado.');
      }else{
        this._resourcesService.openSnackBar(error.error.msg);
      }
    }
  }

  getOrderStartHour(dateStr: string): string{
    let dateTimeArr = dateStr.split(' ');
    let timeArr = dateTimeArr[1].split(':');
    let hour = parseInt(timeArr[0]);
    let period = hour < 12 ? 'AM' : 'PM';
    
    hour = hour > 12 ? hour - 12 : hour;
    
    if(dateTimeArr[0] == '0001-01-01'){
      return '-';
    }
    
    return `${hour}:${timeArr[1]} ${period}`;
  }

  canEditEndDate(): boolean{
    return this.preventiveOrder?.TIPOACTIVADOR == 'Medida' || this.preventiveOrder?.TIPOACTIVADOR == 'Valor';
  }

  getStateTxt(state: string): string{
    if(state == 'A') return "Activo";
    return "";
  }

  getPriorityStr(priority: string): string{
    if(priority == '1'){
      return "Muy alta";
    }else if(priority == '2'){
      return "Alta";
    }else if(priority == '3'){
      return "Media";
    }else if(priority == '4'){
      return "Baja";
    }
    return "";
  }

  getActivatorConfigStr(): string{
    let type = this.preventiveOrder?.TIPOACTIVADOR;
    let configStr = "";

    if(type == 'Calendario' || type == 'Sintoma'){
      let repeat = this.activatorConfig.repeat;
      switch(repeat){
        case "NR": 
          configStr += "La orden no se repite"; 
        break;
        case "AN":
          let repeatDateAn= new Date(this.activatorConfig.startDate);
          configStr += `La orden se repite anualmente el día ${repeatDateAn.getDate()} de ${this.MONTHS[repeatDateAn.getMonth()]}`;
        break;
        case "ME":
          let repeatDateMe = new Date(this.activatorConfig.startDate);
          configStr += `La orden se repite mensualmente los días ${repeatDateMe.getDate()}`;
        break;
        case "SE":
          let repeatDateSe = new Date(this.activatorConfig.startDate);
          configStr += `La orden se repite semanalmente los días ${this.dayNames[repeatDateSe.getDay()]}`;
        break;
        case "TD":
          let repeatDateTd = new Date(this.activatorConfig.startDate);
          configStr += `La orden se repite todos los días desde el ${repeatDateTd.getDate()} de ${this.MONTHS[repeatDateTd.getMonth()]} del ${repeatDateTd.getFullYear()}`;
        break;
        case "PE":
          let repeatDatePe = new Date(this.activatorConfig.startDate);
          let customRepeat = JSON.parse(this.activatorConfig.customRepeat);
          let repeatEvery = customRepeat.repeatEvery.split('|');

          switch(repeatEvery[1]){
            case "0":
              let intervalA = parseInt(repeatEvery[0]);
              if(intervalA > 1){
                configStr += `La orden se repite cada ${intervalA} días `;
              }else{
                configStr += `La orden se repite cada día `;
              }
            break;
            case "1":
              let intervalB = parseInt(repeatEvery[0]);
              if(intervalB > 1){
                configStr += `La orden se repite cada ${intervalB} semanas `;
              }else{
                configStr += `La orden se repite cada semana `;
              }
              
              let repeatOnVals = Object.values(customRepeat.repeatOn);
              let ind = 0;
              let cont = 0;
              let daysStr = "";

              repeatOnVals.forEach(val => {
                if(val){
                  daysStr += `${this.dayNames[ind]}, `;
                  cont++;
                }

                ind++;
              });

              daysStr = daysStr.substring(0, daysStr.length - 2);
              if(cont > 1){
                configStr += `los días ${daysStr} `;
              }else{
                configStr += `el día ${daysStr} `;
              }
            break;
            case "2":
              let intervalC = parseInt(repeatEvery[0]);
              if(intervalC > 1){
                configStr += `La orden se repite cada ${intervalC} meses `;
              }else{
                configStr += `La orden se repite cada mes `;
              }
            break;
            case "3":
              let intervalD = parseInt(repeatEvery[0]);
              if(intervalD > 1){
                configStr += `La orden se repite cada ${intervalD} años `;
              }else{
                configStr += `La orden se repite cada año `;
              }
            break;
          }

          configStr += `a partir del ${repeatDatePe.getDate()} de ${this.MONTHS[repeatDatePe.getMonth()]} del ${repeatDatePe.getFullYear()}, `;
          let endsAt = customRepeat.endsAt.split('|');
          if(endsAt[0] == 'N'){
            configStr += `sin parámetros de finalización.`;
          }else if(endsAt[0] == 'O'){
            let dateArr = endsAt[1].split('-');
            let dateObj = new Date(parseInt(dateArr[0]), parseInt(dateArr[1]), parseInt(dateArr[2]));
            configStr += `finaliza el día ${dateObj.getDate()} de ${this.MONTHS[dateObj.getMonth()]} del ${dateObj.getFullYear()}.`;
          }else if(endsAt[0] == 'A'){
            configStr += `finaliza después de ${endsAt[2]} repetici${parseInt(endsAt[2]) > 1 ? 'ones' : 'ón'}.`;
          }
        break;
      }

      if(type == 'Sintoma'){
        let sign = this.signs[this.activatorConfig.sign];
        configStr += ` Síntoma por revisar: ${sign}`;
      }
    }else{
      if(this.activatorConfig.customUnit != null){
        configStr += `Magnitud medida: ${this.activatorConfig.customMagnitude}. `;
        configStr += `Unidad configurada: ${this.activatorConfig.customUnit}. `;
      }else{
        let magnitude = this.magnitudes.filter(item => item.MAGNITUDE == this.activatorConfig.magnitude)[0];
        let unit = magnitude.UNITS.filter(item => item.UNIT == this.activatorConfig.unit)[0];

        configStr += `Magnitud medida: ${magnitude.LABEL}. `;
        configStr += `Unidad configurada: ${unit.LABEL}. `;
      }

      if(type == 'Medida'){
        configStr += `Valor mínimo: ${this.formatNumbers(this.activatorConfig.minValue)}. `;
        configStr += `Valor máximo: ${this.formatNumbers(this.activatorConfig.maxValue)}`;
      }else{
        configStr += `Valor límite: ${this.formatNumbers(this.activatorConfig.limitValue)}. `;
        if(this.activatorConfig.comparison == 'AC'){
          configStr += "Comparación con el valor acumulado.";
        }else{
          configStr += "Comparación con el último valor reportado.";
        }
      }
    }
    
    return configStr;
  }

  formatNumbers(number: string | number): string{
    let numberStr = `${number}`;
    let numberArr = numberStr.split('').reverse();

    let num = "";
    for(let i = 0; i < numberArr.length - 1; i++){
      let res = i % 3;
      if(res == 2){
        num += `${numberArr[i]},`;
      }else{
        num += `${numberArr[i]}`;
      }
    }

    num += `${numberArr[numberArr.length - 1]}`;
    let numFn = num.split('').reverse().join('');
    
    return numFn;
  }

  async saveChanges(){
    try{
      this.isLoading = true;

      let idUser = localStorage.getItem('idusuario');
      let idOrderEnc = await this._encService.encrypt(`${this.preventiveOrder!.IDORDEN}`);
      let idActiEnc = await this._encService.encrypt(`${this.preventiveOrder!.ACTIVADOR}`);
      let formData = new FormData();

      formData.append('id_user', idUser!);
      formData.append('linea', '1');
      formData.append('id_order', idOrderEnc);
      formData.append('id_activator', idActiEnc);
      formData.append('start_date', this.preventiveOrder!.FECHAINICIO);
      formData.append('end_date', this.preventiveOrder!.FECHAFINAL);
      formData.append('activator_type', this.preventiveOrder!.TIPOACTIVADOR);
      formData.append('priority', this.preventiveOrder!.PRIORIDAD);
      formData.append('config_activator', this.preventiveOrder!.CONFIGACTIVADOR);

      await lastValueFrom(this._prevMaintService.updateOrderWithActivator(formData));

      this._resourcesService.openSnackBar('La orden de trabajo y el activador se actualizaron correctamente.');
      this.isLoading = false;
    }catch(error: any){
      if(error.error == undefined){
        this._resourcesService.openSnackBar('Ocurrió un error inesperado.');
      }else if(error.error.msg == undefined){
        this._resourcesService.openSnackBar('Ocurrió un error inesperado.');
      }else{
        this._resourcesService.openSnackBar(error.error.msg);
      }

      this.isLoading = false;
    }
  }

  goBack(steps: number){
    window.history.go(steps * -1);
  }
}
