import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core';
import { MatTableDataSource } from '@angular/material/table';
import { EquipmentsListItem, EquipmentsListResponse } from '../../../../interfaces/equipment-management.interface';
import { CatalogFailure, ResponseDataGetCatalogFailure } from '../../../../interfaces/failure-analysis/catalog-failure.interface';
import { SelectionModel } from '@angular/cdk/collections';
import { MatPaginator } from '@angular/material/paginator';
import { CatalogMeasures, ResponseDataGetCatalogMeasures } from '../../../../interfaces/failure-analysis/catalog-measures.interface';
import { lastValueFrom, map, Observable, startWith } from 'rxjs';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { ResourcesService, ResponseData } from '../../../../services/resources.service';
import { EncService } from '../../../../services/enc.service';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Router } from '@angular/router';
import { FailureAnalysisService } from '../../../../services/failure-analysis/failure-analysis.service';
import { CatalogMeasuresService } from '../../../../services/counters-and-triggers/catalog-measures.service';
import { EquipmentManagementService } from '../../../../services/equipment-management.service';
import { HttpErrorResponse } from '@angular/common/http';
import { RequestDataFormSymptom, ResponseDataSymptomList } from '../../../../interfaces/failure-analysis/symptom.interface';
import { AlertComponent } from '../../../resources/dialogs/alert/alert.component';

@Component({
    selector: 'app-symptom-list-form',
    templateUrl: './symptom-list-form.component.html',
    styleUrl: './symptom-list-form.component.css',
    standalone: false
})
export class SymptomListFormComponent implements OnInit, AfterViewInit {
  public dataSourceEquipment: MatTableDataSource<EquipmentsListItem>;
  public dataSourceFailure: MatTableDataSource<CatalogFailure>;

  public selectionEquipment: SelectionModel<EquipmentsListItem>;
  public selectionFailure: SelectionModel<CatalogFailure>;

  public displayedColumnsEquipment: Array<string>;
  public displayedColumnsFailure: Array<string>;

  @ViewChild('paginatorEquipment') paginatorEquipment!: MatPaginator;
  @ViewChild('paginatorFailure') paginatorFailure!: MatPaginator;

  public arrMeasures: Array<CatalogMeasures>;
  public measuresStr: Array<string>;
  public filteredOptionsMeasures?: Observable<string[]>;

  public isLoading: boolean;
  public isLoadingForm: boolean;
  public titleDialog: string;
  public typeForm: string;
  private idSymptom!: string | null;

  public formGroup: FormGroup;

  constructor(
    public resourcesService: ResourcesService,
    private _encService: EncService,
    private _dialog: MatDialog,
    private _router: Router,
    private _activatedRoute: ActivatedRoute,
    private _failureAnalysisService: FailureAnalysisService,
    private _catalogMeasuresService: CatalogMeasuresService,
    private _equipmentManagementService: EquipmentManagementService,
  ) {

    this.dataSourceEquipment = new MatTableDataSource<EquipmentsListItem>();
    this.dataSourceFailure = new MatTableDataSource<CatalogFailure>();

    this.selectionEquipment = new SelectionModel<EquipmentsListItem>(true, []);
    this.selectionFailure = new SelectionModel<CatalogFailure>(true, []);

    this.displayedColumnsEquipment = [ 'SELECT', 'CODIGO', 'TIPO', 'MODELO' ];
    this.displayedColumnsFailure = [ 'SELECT', 'ID_FALLA', 'NOMBRE_FALLA', 'NIVEL_CRITICIDAD', 'CAUSA_FALLA' ];

    this.arrMeasures = [];
    this.measuresStr = [];

    this.isLoading = false;
    this.isLoadingForm = false;
    this.titleDialog = '';
    this.typeForm = '';
    this.formGroup = this.createFormGroup();
  }

  private createFormGroup() {
    return new FormGroup({
      NOMBRE_SINTOMA: new FormControl('', Validators.required),
      CLASIFICACION: new FormControl('', Validators.required),
      CAUSA: new FormControl('', Validators.required),
      DESCRIPCION: new FormControl('', Validators.required),
      SOLUCION: new FormControl('', Validators.required),
      LIMITE_VALOR: new FormControl('', Validators.required),
      ID_MEDIDA: new FormControl('', Validators.required),
      EQUIPAMIENTOS: new FormControl([], Validators.required),
      FALLAS: new FormControl([], Validators.required),
    });
  }
  
  ngAfterViewInit(): void {
    this.dataSourceEquipment.paginator = this.paginatorEquipment;
    this.dataSourceFailure.paginator = this.paginatorFailure;
  }

  async ngOnInit() {
    this.isLoading = true;
    this.isLoadingForm = true;
    await this.getEquipment();
    await this.getFailureActives();
    await this.getMeasuresActives();
    await this.getDataForm();
    this.isLoading = false;
    this.isLoadingForm = false;

    this.selectionEquipment.changed.subscribe((equipment) => {
      let arrEquipmentCode: Array<string> = equipment.source.selected.map((equipmentsListItem: EquipmentsListItem) => equipmentsListItem.CODIGO);
      this.formGroup.controls['EQUIPAMIENTOS'].setValue(arrEquipmentCode);
    });
    this.selectionFailure.changed.subscribe((failure) => {
      let arrFailureId: Array<string> = failure.source.selected.map((catalogFailure: CatalogFailure) => catalogFailure.ID_FALLA.toString());
      this.formGroup.controls['FALLAS'].setValue(arrFailureId);
    });
    this.filteredOptionsMeasures = this.formGroup.controls['ID_MEDIDA'].valueChanges.pipe(
      startWith(''),
      map( value => {
        value = value === null || value === undefined ? '' : value;
        const filterValue = value.toLowerCase();
        return this.measuresStr.filter(item => item.toLowerCase().includes(filterValue));
      })
    );
  }

  private async getEquipment() {
    const user: string = this.resourcesService.getUser();
    const line: number = this.resourcesService.getLineNumber();

    await lastValueFrom(this._equipmentManagementService.equipmentConsult(user,line)).then(
      async ( responseData: EquipmentsListResponse ) => {
        if ( !responseData.error ) {

          let arrEquipment: Array<EquipmentsListItem> = [];
          await Promise.all(
            responseData.response.map(async (equipmentsListItem: EquipmentsListItem) => {
              let equipment: EquipmentsListItem = {
                CODIGO: await this._encService.decrypt(equipmentsListItem.CODIGO),
                TIPO: equipmentsListItem.TIPO,
                MODELO: equipmentsListItem.MODELO,
                ID_EQUIPO: await this._encService.decrypt(equipmentsListItem.ID_EQUIPO),
                ESTADO_FUNCIONAMIENTO: equipmentsListItem.ESTADO_FUNCIONAMIENTO,
                ELEMENTO_ORIGEN: equipmentsListItem.ELEMENTO_ORIGEN,
                TIPO_CODIGO: equipmentsListItem.TIPO_CODIGO,
                EQUIPO_PADRE: equipmentsListItem.EQUIPO_PADRE,
                TIENE_HIJOS: equipmentsListItem.TIENE_HIJOS
              };
              arrEquipment.push(equipment);
            })
          );          
          
          this.dataSourceEquipment.data = arrEquipment;

        } else {
          this.resourcesService.openSnackBar(`${responseData.msg}`);
        }
      }, async (httpErrorResponse: HttpErrorResponse) => {
        let response = this.resourcesService.checkErrors(httpErrorResponse)
        if (response !== null && response.reload) {
          await this.getEquipment();
        }
      }
    );
  }

  private async getFailureActives() {
    const user: string = this.resourcesService.getUser();
    const line: number = this.resourcesService.getLineNumber();
    await lastValueFrom( this._failureAnalysisService.getCatalogFailureActives(user, line)).then(
      async (responseData: ResponseDataGetCatalogFailure) => {
        if ( !responseData.error ) {
          this.dataSourceFailure.data = responseData.response;
        } else {
          this.resourcesService.openSnackBar(`${responseData.msg}`);
        }
      }, async (httpErrorResponse: HttpErrorResponse) => {
        let response = this.resourcesService.checkErrors(httpErrorResponse)
        if (response !== null && response.reload) {
          await this.getFailureActives();
        }
      }
    );
  }

  private async getMeasuresActives() {
    let idUser = localStorage.getItem('idusuario')!;
    const LINE: number = this.resourcesService.getLineNumber();
    await lastValueFrom( this._catalogMeasuresService.getCatalogMeasuresActives(idUser, LINE) ).then(
      (responseData: ResponseDataGetCatalogMeasures) => {
        if ( !responseData.error ) {
          this.arrMeasures = responseData.response;
          this.measuresStr = responseData.response.map((catalogMeasures:CatalogMeasures) => `${catalogMeasures.NOMBRE_MEDIDA} - ${catalogMeasures.ACRONIMO_MEDIDA} (${catalogMeasures.ID_MEDIDA})` )
        } else {
          this.resourcesService.openSnackBar(`${responseData.msg}`);
        }
      }, async (httpErrorResponse: HttpErrorResponse) => {
        let response = this.resourcesService.checkErrors(httpErrorResponse)
        if (response !== null && response.reload) {
          await this.getMeasuresActives();
        }
      }
    );
  }
  
  private async getDataForm() {
    const encTypeRequest = this._activatedRoute.snapshot.paramMap.get('form');
    if (encTypeRequest !== null) {
      const strDataForm = await this._encService.decrypt(encTypeRequest);
      const dataTypeRequest: DataDialogSymptomList = JSON.parse(strDataForm);
      this.idSymptom = dataTypeRequest.idSymptomList;
      this.typeForm = dataTypeRequest.type;
      
      if (this.typeForm === 'REG') {
        this.titleDialog = `Registro de Síntoma`;
      } else if (this.typeForm === 'UPD' && this.idSymptom !== null) {
        this.titleDialog = `Modificación de Síntoma`;
        await this.getSymptomById();
      }

    } else {
      this.resourcesService.openSnackBar(`Ocurrió un error al obtener los datos del formulario.`);
      this._router.navigate([`/sam/ANFA/CLSI`]);
    }    
  }
  
  private async getSymptomById() {
    if (this.idSymptom !== null) {
      const encIdSymptom: string = await this._encService.encrypt(this.idSymptom.toString());
      const user: string = this.resourcesService.getUser();
      const line: number = this.resourcesService.getLineNumber();
      await lastValueFrom( this._failureAnalysisService.getSymptomById(encIdSymptom, user, line) ).then(
        (responseData: ResponseDataSymptomList) => {
          if ( !responseData.error && Object.keys(responseData.response).length > 0) {
            this.formGroup.controls['NOMBRE_SINTOMA'].setValue(responseData.response.NOMBRE_SINTOMA);
            this.formGroup.controls['CLASIFICACION'].setValue(responseData.response.CLASIFICACION);
            this.formGroup.controls['CAUSA'].setValue(responseData.response.CAUSA);
            this.formGroup.controls['DESCRIPCION'].setValue(responseData.response.DESCRIPCION);
            this.formGroup.controls['SOLUCION'].setValue(responseData.response.SOLUCION);
            this.formGroup.controls['LIMITE_VALOR'].setValue(responseData.response.LIMITE_VALOR);
            this.formGroup.controls['ID_MEDIDA'].setValue(`${responseData.response.NOMBRE_MEDIDA} - ${responseData.response.ACRONIMO_MEDIDA} (${responseData.response.ID_MEDIDA})`);

            let arrEquipment: Array<string> = responseData.response.EQUIPAMIENTOS.map((equipmentsListItem:EquipmentsListItem) => equipmentsListItem.CODIGO );
            this.formGroup.controls['EQUIPAMIENTOS'].setValue(arrEquipment);
            let arrFailure: Array<string> = responseData.response.FALLAS.map((catalogFailure:CatalogFailure) => catalogFailure.ID_FALLA.toString() );
            this.formGroup.controls['FALLAS'].setValue(arrFailure);

            this.dataSourceEquipment.data.map((equipmentsListItem:EquipmentsListItem) => {
              if (arrEquipment.includes(equipmentsListItem.CODIGO)) {
                this.selectionEquipment.toggle(equipmentsListItem);
              }
            });
            this.dataSourceFailure.data.map((catalogFailure:CatalogFailure) => {
              if (arrFailure.includes(catalogFailure.ID_FALLA.toString())) {
                this.selectionFailure.toggle(catalogFailure);
              }
            });
          } else {
            this.resourcesService.openSnackBar(`${responseData.msg}`);
          }
        }, async (httpErrorResponse: HttpErrorResponse) => {
          let response = this.resourcesService.checkErrors(httpErrorResponse)
          if (response !== null && response.reload) {
            await this.getSymptomById();
          }
        }
      );
    }
  }

  toggleAllRowsEquipment() {
    if (this.isAllSelectedEquipment()) {
      this.selectionEquipment.clear();
      return;
    }
    this.selectionEquipment.select(...this.dataSourceEquipment.data);
  }

  isAllSelectedEquipment() {
    const numSelected = this.selectionEquipment.selected.length;
    const numRows = this.dataSourceEquipment.data.length;
    return numSelected === numRows;
  }

  checkboxLabelEquipment(row?: EquipmentsListItem): string {    
    if (!row) {
      return `${this.isAllSelectedEquipment() ? 'deselect' : 'select'} all`;
    }
    return `${this.selectionEquipment.isSelected(row) ? 'deselect' : 'select'} row ${row.CODIGO}`;
  }

  toggleAllRowsFailure() {
    if (this.isAllSelectedFailure()) {
      this.selectionFailure.clear();
      return;
    }
    this.selectionFailure.select(...this.dataSourceFailure.data);
  }

  isAllSelectedFailure() {
    const numSelected = this.selectionFailure.selected.length;
    const numRows = this.dataSourceFailure.data.length;
    return numSelected === numRows;
  }

  checkboxLabelFailure(row?: CatalogFailure): string {    
    if (!row) {
      return `${this.isAllSelectedFailure() ? 'deselect' : 'select'} all`;
    }
    return `${this.selectionFailure.isSelected(row) ? 'deselect' : 'select'} row ${row.ID_FALLA}`;
  }

  public saveForm() {    
    if ( this.typeForm === 'REG' ) {
      this._dialog.open(AlertComponent, {
        disableClose: true,
        data: {
          title: `Registro de Síntoma`,
          description: `¿Está seguro de realizar el registro del síntoma?`,
          icon: `warning`
        }
      }).afterClosed().subscribe((result: boolean) => {
        if ( result ) {
          this.registerSymptom();
        }
      });
    } else if (this.typeForm === 'UPD') {
      this._dialog.open(AlertComponent, {
        disableClose: true,
        data: {
          title: `Modificación de Síntoma`,
          description: `¿Está seguro de realizar la modificación del síntoma?`,
          icon: `warning`
        }
      }).afterClosed().subscribe((result: boolean) => {
        if ( result ) {
          this.updateSymptom();
        }
      });
    }
  }

  private async registerSymptom() {
    const requestForm: RequestDataFormSymptom = this.createRequestForm();
    await lastValueFrom(this._failureAnalysisService.registerSymptom(requestForm)).then(
      ( responseData: ResponseData ) => {
        if ( !responseData.error ) {
          this.resourcesService.openSnackBar(`¡Registro exitoso!`);
          this._router.navigate(['/sam/ANFA/CLSI']);
        } else {
          this.resourcesService.openSnackBar(`${responseData.msg}`);
        }
      }, async (httpErrorResponse: HttpErrorResponse) => {
        let response = this.resourcesService.checkErrors(httpErrorResponse)
        if (response !== null && response.reload) {
          await this.registerSymptom();
        }
      }
    );
  }

  private createRequestForm() : RequestDataFormSymptom {

    let nombre_sintoma = this.formGroup.controls['NOMBRE_SINTOMA'].value;
    nombre_sintoma = nombre_sintoma.toString().trim();

    let clasificacion = this.formGroup.controls['CLASIFICACION'].value;
    clasificacion = clasificacion.toString().trim();

    let causa = this.formGroup.controls['CAUSA'].value;
    causa = causa.toString().trim();

    let descripcion = this.formGroup.controls['DESCRIPCION'].value;
    descripcion = descripcion.toString().trim();

    let solucion = this.formGroup.controls['SOLUCION'].value;
    solucion = solucion.toString().trim();

    let limite_valor = this.formGroup.controls['LIMITE_VALOR'].value;
    limite_valor = limite_valor.toString().trim();

    let id_medida = this.formGroup.controls['ID_MEDIDA'].value;
    id_medida = id_medida.toString().trim();
    id_medida = id_medida.split('(')[1].split(')')[0];

    let fallas = this.formGroup.controls['FALLAS'].value;

    let equipamientos = this.formGroup.controls['EQUIPAMIENTOS'].value;


    let requestFormMeasures: RequestDataFormSymptom = {
      ID_SINTOMA: this.idSymptom,
      NOMBRE_SINTOMA: nombre_sintoma,
      CLASIFICACION: clasificacion,
      CAUSA: causa,
      DESCRIPCION: descripcion,
      SOLUCION: solucion,
      LIMITE_VALOR: limite_valor,
      ID_MEDIDA: id_medida,
      FALLAS: fallas,
      EQUIPAMIENTOS: equipamientos,
      USUARIO: this.resourcesService.getUser(),
      NUMERO_LINEA: this.resourcesService.getLineNumber(),
    }

    return requestFormMeasures;
  }

  private async updateSymptom() {
    const requestForm: RequestDataFormSymptom = this.createRequestForm();
    await lastValueFrom(this._failureAnalysisService.updateSymptom(requestForm)).then(
      ( responseData: ResponseData ) => {
        if ( !responseData.error ) {
          this.resourcesService.openSnackBar(`¡Modificación exitosa!`);
          this._router.navigate(['/sam/ANFA/CLSI']);
        } else {
          this.resourcesService.openSnackBar(`${responseData.msg}`);
        }
      }, async (httpErrorResponse: HttpErrorResponse) => {
        let response = this.resourcesService.checkErrors(httpErrorResponse)
        if (response !== null && response.reload) {
          await this.updateSymptom();
        }
      }
    );
  }
}

export interface DataDialogSymptomList {
  type: 'REG' | 'UPD';
  idSymptomList: string | null;
}