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

@Component({
    selector: 'app-analysis-filter-equation-failures',
    templateUrl: './analysis-filter-equation-failures.component.html',
    styleUrl: './analysis-filter-equation-failures.component.css',
    standalone: false
})
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 _failureAnalysisService: FailureAnalysisService,
  ) {
    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();
  }

  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),
    });
  }
  
  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 async getCatalogFailureByClassification(classification: string) {
    this.isLoadingForm = true;
    this.isLoadingFailures = true;
    this.formGroup.controls['NOMBRE_FALLA'].disable();
    let encClassification: string = await this._encService.encrypt(classification);
    const user: string = this.resourcesService.getUser();
    const line: number = this.resourcesService.getLineNumber();
    await lastValueFrom(this._failureAnalysisService.getCatalogFailureByClassification(encClassification, user, line)).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}`);
        }
      }, async (httpErrorResponse: HttpErrorResponse) => {
        let response = this.resourcesService.checkErrors(httpErrorResponse)
        if (response !== null && response.reload) {
          await this.getCatalogFailureByClassification(classification);
        }
      }
    );
    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);
    const user: string = this.resourcesService.getUser();
    const line: number = this.resourcesService.getLineNumber();
    await lastValueFrom(this._failureAnalysisService.getEquipmentByFailure(encFailure, user, line)).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}`);
        }
      }, async (httpErrorResponse: HttpErrorResponse) => {
        let response = this.resourcesService.checkErrors(httpErrorResponse)
        if (response !== null && response.reload) {
          await this.getEquipmentByFailure(failure);
        }
      }
    );
    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 || strClassification === '') {
      this.resourcesService.openSnackBar(`Debe seleccionar una clasificación.`);
      this.isLoadingFilter = false;
      return;
    }
    strClassification = strClassification.toString().trim();
    if (!this.clasificateStr.includes(strClassification)) {
      this.resourcesService.openSnackBar(`La clasificación no es válida.`);
      this.isLoadingFilter = false;
      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 es requerido.`);
      this.isLoadingFilter = false;
      return;
    }
    strNombreFalla = strNombreFalla.toString().trim();
    if (!strNombreFalla.includes('(') || !strNombreFalla.includes(')')) {
      this.resourcesService.openSnackBar(`El nombre de la falla no es válido.`);
      this.isLoadingFilter = false;
      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 se encuentra en la lista de fallas, favor de selecconar una falla de la lista despegable.`);
      this.isLoadingFilter = false;
      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.`);
      this.isLoadingFilter = false;
      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.`);
      this.isLoadingFilter = false;
      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.`);
      this.isLoadingFilter = false;
      return;
    }
    const dateStart: Date = strFechaInicio;
    if (dateStart === null || dateStart === undefined) {
      this.resourcesService.openSnackBar(`La fecha inicial no es válida.`);
      this.isLoadingFilter = false;
      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.`);
      this.isLoadingFilter = false;
      return;
    }
    const dateEnd: Date = strFechaFin;
    if (dateEnd === null || dateEnd === undefined) {
      this.resourcesService.openSnackBar(`La fecha inicial no es válida.`);
      this.isLoadingFilter = false;
      return;
    }
    this.analisysInformation.dateEnd = this.resourcesService.getDateFormatCalendar(dateEnd);


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

    const REQUEST: RequestGenerateMTBF = {
      ID_FALLA: idFailure,
      CODIGO_EQUIPAMIENTO: codeEquipment,
      FECHA_INICIO: this.resourcesService.getDateFormatCalendar(dateStart),
      FECHA_FINAL: this.resourcesService.getDateFormatCalendar(dateEnd),
      NUMERO_LINEA: this.resourcesService.getLineNumber(),
      USUARIO: this.resourcesService.getUser(),
    }

    await lastValueFrom(this._failureAnalysisService.generateMTBF(REQUEST)).then(
      (responseData: ResponseDataGenerateMTBF) => {
        if (!responseData.error) {


          let HORAS_FUNCIONAMIENTO = responseData.response.HORAS_FUNCIONAMIENTO === 1 ? `${responseData.response.HORAS_FUNCIONAMIENTO} hora` : `${responseData.response.HORAS_FUNCIONAMIENTO} horas`;
          let CANTIDAD_MANTENIMIENTO_PREVENTIVO = responseData.response.CANTIDAD_MANTENIMIENTO_PREVENTIVO === 1 ? `${responseData.response.CANTIDAD_MANTENIMIENTO_PREVENTIVO} orden` : `${responseData.response.CANTIDAD_MANTENIMIENTO_PREVENTIVO} órdenes`;
          let CANTIDAD_FALLAS_TOTALES = responseData.response.CANTIDAD_FALLAS_TOTALES === 1 ? `${responseData.response.CANTIDAD_FALLAS_TOTALES} falla` : `${responseData.response.CANTIDAD_FALLAS_TOTALES} fallas`;
          let HORAS_INACTIVIDAD = responseData.response.HORAS_INACTIVIDAD === 1 ? `${responseData.response.HORAS_INACTIVIDAD} hora` : `${responseData.response.HORAS_INACTIVIDAD} horas`;
          let MTBF = responseData.response.MTBF === 1 ? `${responseData.response.MTBF} hora` : `${responseData.response.MTBF} horas`;
          
          this.analisysInformation.equipment = codeEquipment;
          this.analisysInformation.classification = this.formGroup.controls['CLASIFICACION'].value;
          this.analisysInformation.failure = this.formGroup.controls['NOMBRE_FALLA'].value;
          this.analisysInformation.dateFirst = this.resourcesService.getDateFormatCalendarFormat(dateStart);
          this.analisysInformation.dateEnd = this.resourcesService.getDateFormatCalendarFormat(dateEnd);
          this.analisysInformation.hoursOperation = HORAS_FUNCIONAMIENTO;
          this.analisysInformation.preventiveMaintenance = CANTIDAD_MANTENIMIENTO_PREVENTIVO;
          this.analisysInformation.numberFailure = CANTIDAD_FALLAS_TOTALES;
          this.analisysInformation.inactivityTime = HORAS_INACTIVIDAD;
          this.analisysInformation.hoursByFailure = MTBF;
        } else {
          this.resourcesService.openSnackBar(`${responseData.msg}`);
        }
      }, async (httpErrorResponse: HttpErrorResponse) => {
        let response = this.resourcesService.checkErrors(httpErrorResponse)
        if (response !== null && response.reload) {
          await this.generateMTBF(idFailure, codeEquipment, dateStart, dateEnd);
        }
      }
    )

    this.isLoadingFilter = false;
  }
}

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