import { HttpErrorResponse } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { Observable, lastValueFrom, map, startWith } from 'rxjs';
import { CatalogFailure, ResponseDataCatalogFailure, ResponseDataGetCatalogFailure } from 'src/app/interfaces/failure-analysis/catalog-failure.interface';
import { EquipmentByFailure, ResponseDataGetEquipmentByFailure } from 'src/app/interfaces/failure-analysis/statistical-analysis';
import { EncService } from 'src/app/services/enc/enc.service';
import { FailureListService } from 'src/app/services/failure-analysis/failure-list.service';
import { ResourcesService } from 'src/app/services/resources/resources.service';

@Component({
  selector: 'app-analysis-filter-equation-failures',
  templateUrl: './analysis-filter-equation-failures.component.html',
  styleUrls: ['./analysis-filter-equation-failures.component.css']
})
export class AnalysisFilterEquationFailuresComponent implements OnInit {

  public isLoading: boolean;
  public isLoadingForm: boolean;
  public isLoadingFilter: boolean;
  public isFilter: boolean;

  public formGroup: FormGroup;
  public analisysInformation: AnalisysInformation

  public arrFailure: Array<CatalogFailure>;
  public arrEquipment: Array<EquipmentByFailure>;

  public isLoadingFailures: boolean;
  public isLoadingEquipment: boolean;

  public clasificateStr: Array<string>;
  public failureStr: Array<string>;
  public equipmentStr: Array<string>;

  public filteredOptionsClasificate?: Observable<string[]>;
  public filteredOptionsFailure?: Observable<string[]>;
  public filteredOptionsEquipment?: Observable<string[]>;

  constructor(
    public resourcesService: ResourcesService,
    private _encService: EncService,
    private _failureListService: FailureListService,
  ) {
    this.isLoading = false;
    this.isLoadingForm = false;
    this.isLoadingFilter = false;
    this.isFilter = false;

    this.clasificateStr = [ 'Bajo', 'Intermedio', 'Alto', 'Crítico' ];
    this.failureStr = [];
    this.equipmentStr = [];

    this.isLoadingFailures = false;
    this.isLoadingEquipment = false;

    this.arrFailure = [];
    this.arrEquipment = [];

    this.analisysInformation = {} as AnalisysInformation;

    this.formGroup = this.createFormGroup();
    
  }
  
  async ngOnInit() {
    this.filteredOptionsClasificate = this.formGroup.controls['CLASIFICACION'].valueChanges.pipe(
      startWith(''),
      map( value => {
        value = value === null || value === undefined ? '' : value;
        const filterValue = value.toLowerCase();
        return this.clasificateStr.filter(item => item.toLowerCase().includes(filterValue));
      })
    );
    this.filteredOptionsFailure = this.formGroup.controls['NOMBRE_FALLA'].valueChanges.pipe(
      startWith(''),
      map( value => {
        value = value === null || value === undefined ? '' : value;
        const filterValue = value.toLowerCase();
        return this.failureStr.filter(item => item.toLowerCase().includes(filterValue));
      })
    );
    this.filteredOptionsEquipment = this.formGroup.controls['EQUIPAMIENTO'].valueChanges.pipe(
      startWith(''),
      map( value => {
        value = value === null || value === undefined ? '' : value;
        const filterValue = value.toLowerCase();
        return this.equipmentStr.filter(item => item.toLowerCase().includes(filterValue));
      })
    );

    this.formGroup.controls['CLASIFICACION'].valueChanges.subscribe((clasificacion) => {
      if (this.clasificateStr.includes(clasificacion)) {
        this.getCatalogFailureByClassification(clasificacion);
      }
    });

    this.formGroup.controls['NOMBRE_FALLA'].valueChanges.subscribe((failure) => {
      if ( failure.includes('(') && failure.includes(')') ) {

        let idFailure: string = failure.split('(')[1].split(')')[0];
        this.getEquipmentByFailure(idFailure);
      }
    });
  }

  private createFormGroup() {
    const year: number = new Date().getFullYear();
    const startDate: Date = new Date(year, 0, 1);
    const endDate: Date = new Date(year, 11, 31);

    return new FormGroup({
      'FECHA_INICIO': new FormControl<Date | null>(startDate),
      'FECHA_FIN': new FormControl<Date | null>(endDate),
      'CLASIFICACION': new FormControl('', Validators.required),
      'NOMBRE_FALLA': new FormControl({ value: '', disabled: true }, Validators.required),
      'EQUIPAMIENTO': new FormControl({ value: '', disabled: true }, Validators.required),
    });
  }

  private async getCatalogFailureByClassification(classification: string) {
    this.isLoadingForm = true;
    this.isLoadingFailures = true;
    this.formGroup.controls['NOMBRE_FALLA'].disable();
    let encClassification: string = await this._encService.encrypt(classification);
    await lastValueFrom(this._failureListService.getCatalogFailureByClassification(encClassification)).then(
      (responseData: ResponseDataGetCatalogFailure) => {
        if (!responseData.error) {
          this.arrFailure = responseData.response;
          if (this.arrFailure.length > 0) {
            this.failureStr = responseData.response.map((catalogFailure: CatalogFailure) => `${catalogFailure.NOMBRE_FALLA} (${catalogFailure.ID_FALLA})`);
            this.formGroup.controls['NOMBRE_FALLA'].enable();
          } else {
            this.resourcesService.openSnackBar(`No existen fallas registradas en la clasificación #${classification}.`);
          }
        } else {
          this.resourcesService.openSnackBar(`${responseData.msg}`);
        }
      }, ( httpErrorResponse: HttpErrorResponse ) => this.resourcesService.checkErrors(httpErrorResponse)
    );
    this.isLoadingFailures = false;
    this.isLoadingForm = false;
  }

  private async getEquipmentByFailure(failure: string) {
    this.isLoadingForm = true;
    this.isLoadingEquipment = true;
    this.formGroup.controls['EQUIPAMIENTO'].disable();
    const encFailure: string = await this._encService.encrypt(failure);
    await lastValueFrom(this._failureListService.getEquipmentByFailure(encFailure)).then(
      (responseData: ResponseDataGetEquipmentByFailure) => {
        if (!responseData.error) {
          this.arrEquipment = responseData.response;
          if (this.arrEquipment.length > 0) {
            this.equipmentStr = responseData.response.map((equipmentByFailure: EquipmentByFailure) => equipmentByFailure.CODIGO_EQUIPAMIENTO);
            this.formGroup.controls['EQUIPAMIENTO'].enable();
          } else {
            this.resourcesService.openSnackBar(`No existen equipamientos registrados en la falla ${failure}.`);
          }
        } else {
          this.resourcesService.openSnackBar(`${responseData.msg}`);
        }
      }, (httpErrorResponse: HttpErrorResponse) => this.resourcesService.checkErrors(httpErrorResponse)
    );
    this.isLoadingEquipment = false;
    this.isLoadingForm = false;
  }

  public async validateValues() {
    this.isLoadingFilter = true;

    if ( this.isFilter === true  ) {
      this.analisysInformation = {} as AnalisysInformation;
      this.isFilter = false;
      this.isLoadingFilter = false;
      return;
    }


    let strClassification = this.formGroup.controls['CLASIFICACION'].value;
    if (strClassification === null || strClassification === undefined) {
      this.resourcesService.openSnackBar(`La clasificación no es válida.`);
      return;
    }
    strClassification = strClassification.toString().trim();
    if (!this.clasificateStr.includes(strClassification)) {
      this.resourcesService.openSnackBar(`La clasificación no es válida.`);
      return;
    }
    this.analisysInformation.classification = strClassification;


    let strNombreFalla = this.formGroup.controls['NOMBRE_FALLA'].value;
    if (strNombreFalla === null || strNombreFalla === undefined) {
      this.resourcesService.openSnackBar(`El nombre de la falla no es válido.`);
      return;
    }
    strNombreFalla = strNombreFalla.toString().trim();
    if (!strNombreFalla.includes('(') || !strNombreFalla.includes(')')) {
      this.resourcesService.openSnackBar(`El nombre de la falla no es válido.`);
      return;
    }
    const idFailure: string = strNombreFalla.split('(')[1].split(')')[0];
    const valdiateFailure: boolean = this.arrFailure.some((catalogFailure: CatalogFailure) => catalogFailure.ID_FALLA.toString() === idFailure)
    if (!valdiateFailure) {
      this.resourcesService.openSnackBar(`El nombre de la falla no es válido.`);
      return;
    }
    this.analisysInformation.failure = strNombreFalla;


    let strEquipamiento = this.formGroup.controls['EQUIPAMIENTO'].value;
    if (strEquipamiento === null || strEquipamiento === undefined) {
      this.resourcesService.openSnackBar(`El código del equipamiento no es válido.`);
      return;
    }
    strEquipamiento = strEquipamiento.toString().trim();
    const valdiateEquipment: boolean = this.arrEquipment.some((equipmentByFailure: EquipmentByFailure) => equipmentByFailure.CODIGO_EQUIPAMIENTO === strEquipamiento);
    if (!valdiateEquipment) {
      this.resourcesService.openSnackBar(`El nombre de la falla no es válido.`);
      return;
    }
    this.analisysInformation.equipment = strEquipamiento;


    let strFechaInicio = this.formGroup.controls['FECHA_INICIO'].value;
    if (strFechaInicio === null || strFechaInicio === undefined) {
      this.resourcesService.openSnackBar(`La fecha inicial no es válida.`);
      return;
    }
    const dateStart: Date = strFechaInicio;
    if (dateStart === null || dateStart === undefined) {
      this.resourcesService.openSnackBar(`La fecha inicial no es válida.`);
      return;
    }
    this.analisysInformation.dateFirst = this.resourcesService.getDateFormatCalendar(dateStart);


    let strFechaFin = this.formGroup.controls['FECHA_FIN'].value;
    if (strFechaFin === null || strFechaFin === undefined) {
      this.resourcesService.openSnackBar(`La fecha final no es válida.`);
      return;
    }
    const dateEnd: Date = strFechaFin;
    if (dateEnd === null || dateEnd === undefined) {
      this.resourcesService.openSnackBar(`La fecha inicial no es válida.`);
      return;
    }
    this.analisysInformation.dateEnd = this.resourcesService.getDateFormatCalendar(dateEnd);


    await this.generateMTBF( strClassification, idFailure, strEquipamiento, dateStart, dateEnd );

  }
  
  private async generateMTBF( clasificacion:string, idFailure:string, codeEquipment:string, dateStart:Date, dateEnd:Date ) {
    this.isFilter = true;

    this.analisysInformation.hoursOperation = '500 horas';
    this.analisysInformation.preventiveMaintenance = '40 mantenimientos preventivos';
    this.analisysInformation.numberFailure = '10 fallas';
    this.analisysInformation.inactivityTime = '30 horas';
    this.analisysInformation.hoursByFailure = '15.6 horas';

    this.isLoadingFilter = false;
  }

  public clearFilter() {
    
  }
}

export interface AnalisysInformation {
  dateFirst: string;
  dateEnd: string;
  classification: string;
  failure: string;
  equipment: string;
  hoursOperation: string;
  preventiveMaintenance: string;
  numberFailure: string;
  inactivityTime: string;
  hoursByFailure: string;
}
