import { SelectionModel } from '@angular/cdk/collections';
import { AfterViewInit, Component, Inject, OnInit, ViewChild } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { EquipmentsListItem, EquipmentsListResponse } from '../../../../interfaces/equipment-management.interface';
import { ResourcesService, ResponseData } from '../../../../services/resources.service';
import { EquipmentManagementService } from '../../../../services/equipment-management.service';
import { FailureAnalysisService } from '../../../../services/failure-analysis/failure-analysis.service';
import { EncService } from '../../../../services/enc.service';
import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
import { HttpErrorResponse } from '@angular/common/http';
import { lastValueFrom } from 'rxjs';
import { RequestFormCatalogFailure, ResponseDataCatalogFailure } from '../../../../interfaces/failure-analysis/catalog-failure.interface';
import { AlertComponent } from '../../../resources/dialogs/alert/alert.component';

@Component({
    selector: 'app-failure-list-form',
    templateUrl: './failure-list-form.component.html',
    styleUrl: './failure-list-form.component.css',
    standalone: false
})
export class FailureListFormComponent implements OnInit, AfterViewInit {
  public isLoading: boolean;
  public titleDialog: string;
  public typeDialog: string;
  
  public formGroup: FormGroup;

  @ViewChild(MatPaginator) paginator!: MatPaginator;
  @ViewChild(MatSort) sort!: MatSort;
  public dataSource: MatTableDataSource<EquipmentsListItem>;
  public selection: SelectionModel<EquipmentsListItem>;
  public displayedColumns: Array<string>;

  constructor(
    public resourcesService: ResourcesService,
    private _equipmentManagementService: EquipmentManagementService,
    private _failureAnalysisService: FailureAnalysisService,
    private _encService: EncService,
    private _dialog: MatDialog,
    private _dialogRef: MatDialogRef<boolean>,
    @Inject(MAT_DIALOG_DATA) public dataDialog: DataDialogFailureList,
  ) {
    this.isLoading = false;
    this.titleDialog = '';
    this.typeDialog = '';
    this.dataSource = new MatTableDataSource<EquipmentsListItem>();
    this.selection = new SelectionModel<EquipmentsListItem>(true, []);
    this.displayedColumns = [ 'SELECT', 'CODIGO', 'TIPO', 'MODELO' ];
    this.formGroup = this.createFormGroup();
  }

  private createFormGroup() {
    return new FormGroup({
      'NOMBRE_FALLA' : new FormControl('', Validators.required),
      'NIVEL' : new FormControl('', Validators.required),
      'CAUSA' : new FormControl('', Validators.required),
      'SOLUCION' : new FormControl('', Validators.required),
      'DESCRIPCION' : new FormControl('', Validators.required),
      'EQUIPAMIENTOS' : new FormControl('', Validators.required),
    });
  }

  async ngOnInit() {
    this.isLoading = true;
    await this.getEquipment();
    await this.getDataDialog();
    this.isLoading = false;

    this.selection.changed.subscribe((element) => {
      let arrEquipmentCode: Array<string> = element.source.selected.map((equipmentsListItem: EquipmentsListItem) => equipmentsListItem.CODIGO);
      this.formGroup.controls['EQUIPAMIENTOS'].setValue(arrEquipmentCode);
    });
  }

  ngAfterViewInit(): void {
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
  }

  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 ) {
          if (responseData.response.length === 0) {
            this.resourcesService.openSnackBar('No existe ningún equipamiento registrado.');
            this._dialogRef.close(false);
          }

          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.dataSource.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 getDataDialog() {
    this.typeDialog = this.dataDialog.type;
    if (this.typeDialog === 'REG') {
      this.titleDialog = 'Registro de causa de falla';
    } else if (this.typeDialog === 'UPD' && this.dataDialog.idCatalogFailure !== null) {
      this.titleDialog = 'Modificación de causa de falla';
      await this.getCatalogFailureById();
    }
  }

  private async getCatalogFailureById() {
    if (this.dataDialog.idCatalogFailure !== null) {
      const encIdFailure: string = await this._encService.encrypt(this.dataDialog.idCatalogFailure.toString());
      const user: string = this.resourcesService.getUser();
      const line: number = this.resourcesService.getLineNumber();
      await lastValueFrom(this._failureAnalysisService.getCatalogFailureById(encIdFailure, user, line)).then(
        async ( responseData: ResponseDataCatalogFailure ) => {
          if (!responseData.error && Object.keys(responseData.response).length > 0 ) {
            
            this.formGroup.controls['NOMBRE_FALLA'].setValue(responseData.response.NOMBRE_FALLA);
            this.formGroup.controls['NIVEL'].setValue(responseData.response.NIVEL_CRITICIDAD);
            this.formGroup.controls['CAUSA'].setValue(responseData.response.CAUSA_FALLA);
            this.formGroup.controls['SOLUCION'].setValue(responseData.response.SOLICION);
            this.formGroup.controls['DESCRIPCION'].setValue(responseData.response.DESCRIPCION);
            let arrEquipmentCode:Array<string> = responseData.response.EQUIPAMIENTOS.map((element: EquipmentsListItem) => element.CODIGO);
            this.formGroup.controls['EQUIPAMIENTOS'].setValue(arrEquipmentCode);

            this.dataSource.data.map((element:EquipmentsListItem) => {
              if (arrEquipmentCode.includes(element.CODIGO)) {
                this.selection.toggle(element);
              }
            })
            

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

  toggleAllRows() {
    if (this.isAllSelected()) {
      this.selection.clear();
      return;
    }
    this.selection.select(...this.dataSource.data);
  }

  isAllSelected() {
    const numSelected = this.selection.selected.length;
    const numRows = this.dataSource.data.length;
    return numSelected === numRows;
  }

  checkboxLabel(row?: EquipmentsListItem): string {    
    if (!row) {
      return `${this.isAllSelected() ? 'deselect' : 'select'} all`;
    }
    return `${this.selection.isSelected(row) ? 'deselect' : 'select'} row ${row.CODIGO}`;
  }

  public async saveForm() {
    let failure: string = this.formGroup.controls['NOMBRE_FALLA'].value;
    failure = failure.trim();

    if (this.typeDialog === 'REG') {
      this._dialog.open( AlertComponent, {
        data: {
          title: `Registro de Causa de Falla`,
          description: `¿Está seguro de registrar la falla ${ failure }?`,
          icon: `warning`
        }
      }).afterClosed().subscribe((result) => {
        if (result) {
          this.registerFailure();
        }
      });
    } else {
      this._dialog.open( AlertComponent, {
        data: {
          title: `Modificación de Causa de Falla`,
          description: `¿Está seguro de modificar la falla ${ failure }?`,
          icon: `warning`
        }
      }).afterClosed().subscribe((result) => {
        if (result) {
          this.updateFailure();
        }
      });
    }    
  }

  private async registerFailure() {
    this.isLoading = true;
    let requestForm: RequestFormCatalogFailure = await this.createRequestForm();
    await lastValueFrom(this._failureAnalysisService.registerCatalogFailure(requestForm)).then(
      (responseData: ResponseData) => {
        if (!responseData.error) {
          this.resourcesService.openSnackBar(`¡Registro exitoso!`);
          this._dialogRef.close(true);
        } else {
          this.resourcesService.openSnackBar(`${responseData.msg}`);
        }
      }, async (httpErrorResponse: HttpErrorResponse) => {
        let response = this.resourcesService.checkErrors(httpErrorResponse)
        if (response !== null && response.reload) {
          await this.registerFailure();
        }
      }
    );
    this.isLoading = false;
  }

  private async createRequestForm(): Promise<RequestFormCatalogFailure>{

    let idFailure = this.dataDialog.idCatalogFailure;
    let nameFailure = this.formGroup.controls['NOMBRE_FALLA'].value;
    let level = this.formGroup.controls['NIVEL'].value;
    let cause = this.formGroup.controls['CAUSA'].value;
    let solution = this.formGroup.controls['SOLUCION'].value;
    let description = this.formGroup.controls['DESCRIPCION'].value;
    let equipment = this.formGroup.controls['EQUIPAMIENTOS'].value;
    let line = this.resourcesService.getLineNumber();
    let user = this.resourcesService.getUser();

    let requestForm: RequestFormCatalogFailure = {
      ID_FALLA: idFailure,
      NOMBRE_FALLA: nameFailure,
      NIVEL: level,
      CAUSA: cause,
      SOLUCION: solution,
      DESCRIPCION: description,
      EQUIPAMIENTOS: equipment,
      NUMERO_LINEA: line,
      USUARIO: user,
    }

    return requestForm;
    
  }

  private async updateFailure() {
    this.isLoading = true;
    let requestForm: RequestFormCatalogFailure = await this.createRequestForm();
    await lastValueFrom(this._failureAnalysisService.updateCatalogFailure(requestForm)).then(
      (responseData: ResponseData) => {
        if (!responseData.error) {
          this.resourcesService.openSnackBar(`¡Modificación exitosa!`);
          this._dialogRef.close(true);
        } else {
          this.resourcesService.openSnackBar(`${responseData.msg}`);
        }
      }, async (httpErrorResponse: HttpErrorResponse) => {
        let response = this.resourcesService.checkErrors(httpErrorResponse)
        if (response !== null && response.reload) {
          await this.updateFailure();
        }
      }
    );
    this.isLoading = false;
  }
}

export interface DataDialogFailureList {
  type: 'REG' | 'UPD';
  idCatalogFailure: string | null;
}