import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ResourcesService } from '../../../../services/resources.service';
import { lastValueFrom } from 'rxjs';
import { CorrectiveMaintenanceService } from '../../../../services/corrective-maintenance.service';
import { CorrectiveMaintenanceOrderField, NoMeasuresFormFieldsListResponse, NoMeasuresOrderResponse } from '../../../../interfaces/corrective-maintenance.interface';
import { EncService } from '../../../../services/enc.service';
import { FunctionsService } from '../../../../services/functions.service';
import { FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms';
import { validColorValidator } from 'ngx-colors';
import { MatDialog } from '@angular/material/dialog';
import { TimePickerComponent } from '../../../resources/dialogs/time-picker/time-picker.component';

@Component({
    selector: 'app-corrective-order-form-without-measures',
    templateUrl: './corrective-order-form-without-measures.component.html',
    styleUrl: './corrective-order-form-without-measures.component.css',
    standalone: false
})
export class CorrectiveOrderFormWithoutMeasuresComponent implements OnInit {
  isLoading: boolean;
  hasError: boolean;
  errorStr: string;
  screenSize: number;
  action: string;
  isNew: boolean;
  formLabel: string;
  savingOrder: boolean;
  idOrder: string | null;

  noMeasuresFormFields: CorrectiveMaintenanceOrderField[];
  noMeasuresFormGroup: FormGroup;
  noMeasuresFormVisibilities: any;

  constructor(
    private _activatedRoute: ActivatedRoute,
    private _resourcesService: ResourcesService,
    private _correctiveMaintenanceService: CorrectiveMaintenanceService,
    private _encService: EncService,
    private _functionsService: FunctionsService,
    private _dialog: MatDialog
  ) {
    this.isLoading = true;
    this.hasError = false;
    this.errorStr = '';
    this.screenSize = window.innerWidth;
    this.action = '';
    this.isNew = true;
    this.formLabel = '';
    this.savingOrder = false;
    this.idOrder = null;

    this.noMeasuresFormFields = [];
    this.noMeasuresFormGroup = new FormGroup({});
    this.noMeasuresFormVisibilities = {};
  }

  ngOnInit(): void {
    this._activatedRoute.queryParams.subscribe(params => {
      let route = window.location.href;
      let actionArr = route.split('/').reverse()[0].split('?');
      let action = actionArr[0];

      let idOrderEnc = params['idOrder'];
      if(idOrderEnc == null || idOrderEnc == undefined || idOrderEnc == ''){
        this._resourcesService.openSnackBar('No se recibieron parametros.');
        this.goBack(1);
      }else if(action == 'nuevo-sin-mediciones'){
        this.isNew = true;
        this.action = 'Registrar';

        this.getNoMeasuresFormFields();
      }else if(action == 'editar-sin-mediciones'){
        this.isNew = false;
        this.action = 'Editar';

        this.getNoMeasuresOrder(idOrderEnc);
      }
    });
  }

  onResize():void{
    this.screenSize = window.innerWidth;
  }

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

  private async getNoMeasuresFormFields(){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let noMeasuresFormFields: NoMeasuresFormFieldsListResponse = await lastValueFrom(this._correctiveMaintenanceService.getNoMeasuresFormFields(idUser, 1));

      this.hasError = noMeasuresFormFields.error;
      this.errorStr = noMeasuresFormFields.msg;

      if(!this.hasError){
        let lastUpdate = this._functionsService.buildLastUpdate(noMeasuresFormFields.response.FECHA_ACTUALIZACION);
        this.formLabel = `V${noMeasuresFormFields.response.VERSION} - Última actualización ${lastUpdate}`;
        
        let noMeasuresFormFieldsArr: CorrectiveMaintenanceOrderField[] = [];
        for(const field of noMeasuresFormFields.response.CAMPOS){
          field.fieldID = await this._encService.decrypt(field.fieldID);
          if(typeof field.cols == 'string'){
            let colsNum = parseInt(field.cols as string);
            field.cols = colsNum;
          }

          if(typeof field.rows == 'string'){
            let rowsNum = parseInt(field.rows as string);
            field.rows = rowsNum;
          }

          noMeasuresFormFieldsArr.push(field);
        }

        this.noMeasuresFormFields = noMeasuresFormFieldsArr;
        this.resetNoMeasuresFormGroup();
      }
      
      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{
        console.log(error.error.msg);
        this.errorStr = error.error.msg;
      }

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

  private async getNoMeasuresOrder(idOrder: string){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let order: NoMeasuresOrderResponse = await lastValueFrom(this._correctiveMaintenanceService.getNoMeasuresOrder(
        idOrder,
        idUser,
        1
      ));

      this.hasError = order.error;
      this.errorStr = order.msg;

      if(!this.hasError){
        let lastUpdate = this._functionsService.buildLastUpdate(order.response.FORMULARIO.FECHA_ACTUALIZACION);
        this.formLabel = `V${order.response.FORMULARIO.VERSION} - Actualización ${lastUpdate}`;
        
        let noMeasuresFormFieldsArr: CorrectiveMaintenanceOrderField[] = [];
        for(const field of order.response.FORMULARIO.CAMPOS){
          field.fieldID = await this._encService.decrypt(field.fieldID);
          if(typeof field.cols == 'string'){
            let colsNum = parseInt(field.cols as string);
            field.cols = colsNum;
          }

          if(typeof field.rows == 'string'){
            let rowsNum = parseInt(field.rows as string);
            field.rows = rowsNum;
          }

          noMeasuresFormFieldsArr.push(field);
        }

        this.noMeasuresFormFields = noMeasuresFormFieldsArr;
        this.resetNoMeasuresFormGroup();
        this.idOrder = order.response.DATOS.ID_REGISTRO;

        let dataDec = await this._encService.decrypt(order.response.DATOS.DATOS);
        
        let dataObj = JSON.parse(dataDec);
        let dataKeys = Object.keys(dataObj);

        for(const key of dataKeys){
          let fieldKey = `${key}Control`;
          let fieldValue = dataObj[key];
          let fieldFilt = this.noMeasuresFormFields.filter(field => field.fieldID == key);

          if(fieldFilt.length > 0){
            if(fieldFilt[0].validators.includes('HORA')){
              let hourArr = fieldValue.split(':');
              let hourNum = parseInt(hourArr[0]);
              let period = hourNum < 12 ? 'AM' : 'PM';
              hourNum = hourNum > 12 ? hourNum - 12 : hourNum;

              fieldValue = `${hourNum}:${hourArr[1]} ${period}`;
            }else if(fieldFilt[0].fieldType == 'FE-2'){
              let dateObj = new Date(`${fieldValue}T00:00:00.000-06:00`);
              fieldValue = dateObj;
            }
          }
          
          this.noMeasuresFormGroup.controls[fieldKey].setValue(fieldValue);
        }
      }

      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;
    }
  }

  resetNoMeasuresFormGroup(){
    this.noMeasuresFormGroup = new FormGroup({});

    for(const field of this.noMeasuresFormFields){
      let validatorsArr = JSON.parse(field.validators);
      let validators: ValidatorFn[] = [];

      for(const validator of validatorsArr){
        if(validator == 'CARE'){
          validators.push(Validators.required);
        }else if(validator == 'LOMI'){
          validators.push(Validators.minLength(field.minLength));
        }else if(validator == 'LOMA'){
          validators.push(Validators.maxLength(field.maxLength));
        }else if(validator == 'COEL'){
          validators.push(Validators.email);
        }else if(validator == 'CONT'){
          this.noMeasuresFormVisibilities[field.fieldID] = false;
        }
      }

      let initialVal: any = null;
      if(field.fieldType == 'TE-1' || field.fieldType == 'CT-3' || field.fieldType == 'SE-4') initialVal = '';
      else if(field.fieldType == 'FE-2') field.defaultDate ? initialVal = new Date() : initialVal = null;
      else if(field.fieldType == 'CL-5') { initialVal = "rgb(79, 195, 255)"; validators.push(validColorValidator()); }

      if(field.defaultHour){
        let date = new Date();
        let timestamp = date.getTime();
        let seconds = Math.trunc(timestamp / 1000);
        let minutesTmp = Math.trunc(seconds / 60) - date.getTimezoneOffset();
        let hoursTmp = Math.trunc(minutesTmp / 60);
        let daysTmp = Math.trunc(hoursTmp / 24);
        
        let overflowedHours = daysTmp * 24;
        let currentHour = hoursTmp - overflowedHours;
    
        let overflowedMinutes = (currentHour * 60) + (daysTmp * 24 * 60);
        let currentMinutes = minutesTmp - overflowedMinutes;
        let period = currentHour < 12 ? 'AM' : 'PM';
        let currentHourFn = currentHour > 12 ? currentHour - 12 : currentHour;
    
        let hourStr = currentHourFn < 10 ? `0${currentHourFn}` : `${currentHourFn}`;
        let minutesStr = currentMinutes < 10 ? `0${currentMinutes}` : `${currentMinutes}`;
        initialVal = `${hourStr}:${minutesStr} ${period}`;
      }

      this.noMeasuresFormGroup.addControl(`${field.fieldID}Control`, new FormControl({value: initialVal, disabled: !field.enabled}, validators));
      if(field.fieldType == 'CL-5'){
        this.noMeasuresFormGroup.addControl(`${field.fieldID}ColorControl`, new FormControl("rgb(79, 195, 255)", validators));
    
        this.noMeasuresFormGroup.controls[`${field.fieldID}Control`].valueChanges.subscribe((color) => {
          if(this.noMeasuresFormGroup.controls[`${field.fieldID}Control`].valid){
            this.noMeasuresFormGroup.controls[`${field.fieldID}ColorControl`].setValue(color, {
              emitEvent: false,
            });
          }
        });
    
        this.noMeasuresFormGroup.controls[`${field.fieldID}ColorControl`].valueChanges.subscribe((color) => {
          this.noMeasuresFormGroup.controls[`${field.fieldID}Control`].setValue(color, {
            emitEvent: false,
          })
        });
      }
    }
  }

  validateInput(value: string | string[], id: string){
    let fieldFilt = this.noMeasuresFormFields.filter(item => item.fieldID == id);
    if(fieldFilt.length > 0){
      let validVal: string | string[] = '';

      if(fieldFilt[0].fieldType == 'TE-1' || fieldFilt[0].fieldType == 'CT-3'){
        value = value as string;
        let validatorsArr = JSON.parse(fieldFilt[0].validators);

        if(validatorsArr.includes('NUME')){
          let validChars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
          let valueArr = value.split('');
          let pointsCounter = 0;

          valueArr.forEach(char => {
            if(fieldFilt[0].includeDecimal && pointsCounter < 1 && char == '.'){
              validVal += '.';
              pointsCounter++;
            }else if(validChars.includes(char)){
              validVal += char;
            }
          });
        }else{
          validVal = value;
        }

        if(validatorsArr.includes('LOMA')){
          validVal = validVal.substring(0, fieldFilt[0].maxLength);
        }
      }else if(fieldFilt[0].fieldType == 'SE-4'){
        if(fieldFilt[0].isMultiple){
          value = value as string[];

          if(value.includes('N')){
            validVal = ['N'];
          }else{
            validVal = value;
          }
        }else{
          value = value as string;
          let optionFilt = fieldFilt[0].selectorOptions.filter(item => item.value == value);
          if(optionFilt.length > 0){
            validVal = optionFilt[0].value;
          }
        }
      }

      this.noMeasuresFormGroup.controls[`${fieldFilt[0].fieldID}Control`].setValue(validVal);
    }
  }

  openHourSelector(value: string, control: string){
    if(this.noMeasuresFormGroup.contains(control)){
      let dialogRef = this._dialog.open(TimePickerComponent, {
        width: '320px',
        maxWidth: '320px',
        disableClose: true,
        data: {
          time: value,
        }
      });
  
      dialogRef.afterClosed().subscribe(res => {
        if(res != null && res != undefined && res != ''){
          this.noMeasuresFormGroup.controls[control].setValue(res);
        }
      });
    }
  }

  async saveNoMeasuresOder(){
    try{
      this.savingOrder = true;

      let idUser = localStorage.getItem('idusuario')!;
      let formValue = this.noMeasuresFormGroup.getRawValue();
      let formKeys = Object.keys(formValue);
      let formObj: any = {};

      for(const key of formKeys){
        let field = key.replace('Control', '');
        let finalVal = '';
        let fieldFilt = this.noMeasuresFormFields.filter(item => item.fieldID == field);

        if(fieldFilt.length > 0){
          if(fieldFilt[0].validators.includes('HORA')){
            if(formValue[key] != null && formValue[key] != undefined && formValue[key] != ''){
              let hourArr = formValue[key].split(' ');
              if(hourArr.length == 2){
                let timeArr = hourArr[0].split(':');
                if(timeArr.length == 2){
                  let hourNum = parseInt(timeArr[0]);
                  let hour = hourNum < 12 && hourArr[1] == 'PM' ? hourNum + 12 : hourNum;
                  let hourStr = hour < 10 ? `0${hour}` : `${hour}`;

                  finalVal = `${hourStr}:${timeArr[1]}:00`;
                }
              }
            }
          }else if(fieldFilt[0].fieldType == 'FE-2'){
            let parsedDate = new Date(formValue[key]);
            if(!isNaN(parsedDate.getTime())){
              let year = parsedDate.getFullYear();
              let month = parsedDate.getMonth() + 1;
              let day = parsedDate.getDate();

              let monthStr = month < 10 ? `0${month}` : `${month}`;
              let dayStr = day < 10 ? `0${day}` : `${day}`;

              finalVal = `${year}-${monthStr}-${dayStr}`;
            }
          }else{
            finalVal = formValue[key];
          }
        }
        
        formObj[field] = finalVal;
      }

      let formStr = JSON.stringify(formObj);
      let formEnc = await this._encService.encrypt(formStr);
      let formData = new FormData();
      
      formData.append('id_user', idUser);
      formData.append('linea', '1');
      formData.append('data', formEnc);

      let orderDec = '';
      if(this.isNew){
        let res = await lastValueFrom(this._correctiveMaintenanceService.saveNoMeasuresOrder(formData));
        orderDec = await this._encService.decrypt(res.response.order);
      }else{
        formData.append('id_order', this.idOrder!);

        await lastValueFrom(this._correctiveMaintenanceService.updateNoMeasuresOrder(formData));
        orderDec = await this._encService.decrypt(this.idOrder!);
      }
      
      this._resourcesService.openSnackBar(`La orden #${orderDec} se guardó correctamente.`);
      this.goBack(1);
    }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.savingOrder = false;
    }
  }
}
