import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { FilterRequest, GetTaskByWorkflow, GetWorkflows, ProcessWorkflow, RequestSearch, ResponseDataFilterRequest, ResponseDataGetTaskByWorkflow, ResponseDataGetWorkflows, ResponseDataProcessWorkflow } from '../../../../interfaces/process-managementv/workflow-management.interface';
import { lastValueFrom, map, Observable, startWith } from 'rxjs';
import { ResourcesService } from '../../../../services/resources.service';
import { InternationalizationService } from '../../../../services/internationalization/internationalization.service';
import { ProcessManagementService } from '../../../../services/process-management/process-management.service';
import { MatDialogRef } from '@angular/material/dialog';
import { EncService } from '../../../../services/enc.service';
import { HttpErrorResponse } from '@angular/common/http';

@Component({
    selector: 'app-search-request',
    templateUrl: './search-request.component.html',
    styleUrl: './search-request.component.css',
    standalone: false
})
export class SearchRequestComponent implements OnInit {
  public formGroup: FormGroup;
  public isLoading: boolean;
  
  private arrWorkflow: GetWorkflows[];
  public arrWorkflowStr: string[];
  public filteredOptionsWorkflow!: Observable<string[]>;
  
  private arrTask: GetTaskByWorkflow[];
  public arrTaskStr: string[];
  public filteredOptionsTask!: Observable<string[]>;
  public isLoadingTask: boolean;

  public arrProcessWorkflow: ProcessWorkflow[];
  public arrProcessWorkflowStr: string[];
  public filteredOptionsProcessWorkflow!: Observable<string[]>;
  
  constructor(
    public resourcesService: ResourcesService,
    public interService: InternationalizationService,
    private _processManagementService: ProcessManagementService,
    private _dialogReg: MatDialogRef<false | FilterRequest[]>,
    private _encService: EncService,
  ) {
    this.formGroup = this._createFormGroup();
    this.isLoading = false;
    this.arrWorkflow = [];
    this.arrWorkflowStr = [];

    this.arrTask = [];
    this.arrTaskStr = [];
    this.isLoadingTask = false;

    this.arrProcessWorkflow = [];
    this.arrProcessWorkflowStr = [];
  }

  private _createFormGroup(): FormGroup {
    return new FormGroup({
      NOMBRE_WORKFLOW: new FormControl( null ),
      NUMERO_EJECUCION_WORKFLOW: new FormControl( null, Validators.min(1) ),
      ESTADO_EJECUCION_WORKFLOW: new FormControl( null ),
      NOMBRE_TAREA: new FormControl( { value: null, disabled: true } ),
      NUMERO_EJECUCION_TAREA: new FormControl( null, Validators.min(1) ),
      ESTADO_EJECUCION_TAREA: new FormControl( null ),
      NOMBRE_PROCESO: new FormControl( null ),
      FECHA_INICIO: new FormControl<Date | null>(null),
      FECHA_FINAL: new FormControl<Date | null>(null),
    });
  }
  
  async ngOnInit() {
    this.isLoading = true;
    await this._getWorkflowsActives();
    await this._getProcessWorkflow();
    this.isLoading = false;


    this.filteredOptionsWorkflow = this.formGroup.controls['NOMBRE_WORKFLOW'].valueChanges.pipe(
      startWith(''),
      map(value => {
        value = value === null || value === undefined ? '' : value;
        const filterValue = value.toLowerCase();
        return this.arrWorkflowStr.filter(option => option.toLowerCase().includes(filterValue));
      })
    );

    this.filteredOptionsTask = this.formGroup.controls['NOMBRE_TAREA'].valueChanges.pipe(
      startWith(''),
      map(value => {
        value = value === null || value === undefined ? '' : value;
        const filterValue = value.toLowerCase();
        return this.arrTaskStr.filter(option => option.toLowerCase().includes(filterValue));
      })
    );

    this.filteredOptionsProcessWorkflow = this.formGroup.controls['NOMBRE_PROCESO'].valueChanges.pipe(
      startWith(''),
      map(value => {
        value = value === null || value === undefined ? '' : value;
        const filterValue = value.toLowerCase();
        return this.arrProcessWorkflowStr.filter(option => option.toLowerCase().includes(filterValue));
      })
    );
  }

  private async _getWorkflowsActives() {
    const user: string = this.resourcesService.getUser();
    const line: number = this.resourcesService.getLineNumber();
    await lastValueFrom(this._processManagementService.getWorkflowsActives(user, line)).then(
      (responseData: ResponseDataGetWorkflows) => {
        if (!responseData.error) {
          this.arrWorkflow = responseData.response;
          this.arrWorkflowStr = responseData.response.map((workflow: GetWorkflows) => `${workflow.NOMBRE_WORKFLOW} (${workflow.ID_WORKFLOW})`);
        } else {
          this.resourcesService.openSnackBar(`${responseData.msg}`);
        }
      }, async (httpErrorResponse: HttpErrorResponse) => {
        let response = this.resourcesService.checkErrors(httpErrorResponse)
        if (response !== null && response.reload) {
          await this._getWorkflowsActives();
        }
      }
    );
  }

  private async _getProcessWorkflow() {
    const user: string = this.resourcesService.getUser();
    const line: number = this.resourcesService.getLineNumber();
    await lastValueFrom(this._processManagementService.getProcessWorkflow(user, line)).then(
      (responseData: ResponseDataProcessWorkflow) => {
        if (!responseData.error) {
          this.arrProcessWorkflow = responseData.response;
          this.arrProcessWorkflowStr = responseData.response.map((processWorkflow: ProcessWorkflow) => `${processWorkflow.NOMBRE_PROCESO} (${processWorkflow.ID_PROCESO})`);
        } else {
          this.resourcesService.openSnackBar(`${responseData.msg}`);
        }
      }, async (httpErrorResponse: HttpErrorResponse) => {
        let response = this.resourcesService.checkErrors(httpErrorResponse)
        if (response !== null && response.reload) {
          await this._getProcessWorkflow();
        }
      }
    );
  }

  public async getTaskByWorkflow(workflow: string) {
    this.isLoadingTask = true;
    if (!workflow.includes('(') || !workflow.includes(')')) {
      this.resourcesService.openSnackBar(`Ocurrió un error al obtener el identificador del flujo de trabajo.`);
      this._dialogReg.close(false);
      return;
    }
    const idWorkflow = workflow.split('(')[1].split(')')[0];
    const validate: boolean = this.arrWorkflow.every((getWorkflows: GetWorkflows) => getWorkflows.ID_WORKFLOW.toString() == idWorkflow);
    if (!validate) {
      this.resourcesService.openSnackBar(`No se pudo encontrar el flujo de trabajo seleccionado.`);
      this._dialogReg.close(false);
      return;
    }
    const encWorkflow: string = await this._encService.encrypt(idWorkflow.toString());
    const user: string = this.resourcesService.getUser();
    const line: number = this.resourcesService.getLineNumber();
    await lastValueFrom(this._processManagementService.getTaskByWorkflow(encWorkflow, user, line)).then(
      (responseData: ResponseDataGetTaskByWorkflow) => {
        if (!responseData.error) {
          this.arrTask = responseData.response;
          this.arrTaskStr = responseData.response.map((task: GetTaskByWorkflow) => `${task.NOMBRE_TAREA} (${task.ID_TAREA})`);
          if (this.arrTaskStr.length > 0) {
            this.formGroup.controls['NOMBRE_TAREA'].enable();
          } else {
            this.formGroup.controls['NOMBRE_TAREA'].disable();
          }
        } else {
          this.resourcesService.openSnackBar(`${responseData.msg}`);
          this.formGroup.controls['NOMBRE_TAREA'].disable();
        }
      }, async (httpErrorResponse: HttpErrorResponse) => {
        let response = this.resourcesService.checkErrors(httpErrorResponse)
        if (response !== null && response.reload) {
          await this.getTaskByWorkflow(workflow);
        } else {
          this.formGroup.controls['NOMBRE_TAREA'].disable();
        }
      }
    );
    this.isLoadingTask = false;
  }

  public async search() {
    this.isLoading = true;

    let nombreWorkflow = this.formGroup.controls['NOMBRE_WORKFLOW'].value;
    if (nombreWorkflow !== null && nombreWorkflow !== undefined && nombreWorkflow !== '') {
      nombreWorkflow = nombreWorkflow.toString().trim();
      if ( !nombreWorkflow.includes('(') || !nombreWorkflow.includes(')') ) {
        this.resourcesService.openSnackBar(`Debe elegir una opción de la lista desplegable en el campo del nombre del workflow`);
        return;
      }
      nombreWorkflow = nombreWorkflow.split('(')[1].split(')')[0];
    } else {
      nombreWorkflow = null;
    }
    

    let numeroEjecucionWorkflow = this.formGroup.controls['NUMERO_EJECUCION_WORKFLOW'].value;
    if (numeroEjecucionWorkflow !== null && numeroEjecucionWorkflow !== undefined && numeroEjecucionWorkflow !== '') {
      numeroEjecucionWorkflow = parseInt(numeroEjecucionWorkflow);
      if ( numeroEjecucionWorkflow <= 0 ) {
        this.resourcesService.openSnackBar(`Ocurrió un error con el formato del número de ejecución del flujo de trabajo.`);
        return;
      }
      if (numeroEjecucionWorkflow % 1 !== 0) {
        this.resourcesService.openSnackBar(`El número de ejecución del flujo de trabajo debe ser un número entero.`);
        return;
      }
    } else {
      numeroEjecucionWorkflow = null;
    }
  

    let estadoEjecucionWorkflow = this.formGroup.controls['ESTADO_EJECUCION_WORKFLOW'].value;
    if (estadoEjecucionWorkflow !== null && estadoEjecucionWorkflow !== undefined && estadoEjecucionWorkflow !== '') {
      estadoEjecucionWorkflow = estadoEjecucionWorkflow.toString().trim();
    } else {
      estadoEjecucionWorkflow = null;
    }


    let nombreTarea = this.formGroup.controls['NOMBRE_TAREA'].value;
    if (nombreTarea !== null && nombreTarea !== undefined && nombreTarea !== '') {
      nombreTarea = nombreTarea.toString().trim();
      if ( !nombreTarea.includes('(') || !nombreTarea.includes(')') ) {
        this.resourcesService.openSnackBar(`Debe elegir una opción de la lista desplegable en el campo del nombre de la tarea.`);
        return;
      }
      nombreTarea = nombreTarea.split('(')[1].split(')')[0];
    } else {
      nombreTarea = null;
    }
    

    let numeroEjecucionTarea = this.formGroup.controls['NUMERO_EJECUCION_TAREA'].value;
    if (numeroEjecucionTarea !== null && numeroEjecucionTarea !== undefined && numeroEjecucionTarea !== '') {
      numeroEjecucionTarea = parseInt(numeroEjecucionTarea);
      if ( numeroEjecucionTarea <= 0 ) {
        this.resourcesService.openSnackBar(`Ocurrió un error con el formato del número de ejecución de la tarea.`);
        return;
      }
      if (numeroEjecucionTarea % 1 !== 0) {
        this.resourcesService.openSnackBar(`El número de ejecución de la tarea debe ser un número entero.`);
        return;
      }
    } else {
      numeroEjecucionTarea = null;
    }
    

    let estadoEjecucionTarea = this.formGroup.controls['ESTADO_EJECUCION_TAREA'].value;
    if (estadoEjecucionTarea !== null && estadoEjecucionTarea !== undefined && estadoEjecucionTarea !== '') {
      estadoEjecucionTarea = estadoEjecucionTarea.toString().trim();
    } else {
      estadoEjecucionTarea = null;
    }
    

    let nombreProceso = this.formGroup.controls['NOMBRE_PROCESO'].value;
    if (nombreProceso !== null && nombreProceso !== undefined && nombreProceso !== '') {
      nombreProceso = nombreProceso.toString().trim();
      if ( !nombreProceso.includes('(') || !nombreProceso.includes(')') ) {
        this.resourcesService.openSnackBar(`Debe elegir una opción de la lista desplegable en el campo del nombre del proceso.`);
        return;
      }
      nombreProceso = nombreProceso.split('(')[1].split(')')[0];
    } else {
      nombreProceso = null;
    }


    let fechaInicio = this.formGroup.controls['FECHA_INICIO'].value;
    let fechaFinal = this.formGroup.controls['FECHA_FINAL'].value;

    if (fechaInicio !== null && fechaInicio !== undefined && fechaInicio !== '') {
      fechaInicio = new Date(fechaInicio);
      fechaInicio = this.resourcesService.getDateFormatCalendar(fechaInicio);
    } else {
      fechaInicio = null;
    }

    if (fechaFinal !== null && fechaFinal !== undefined && fechaFinal !== '') {
      fechaFinal = new Date(fechaFinal);
      fechaFinal = this.resourcesService.getDateFormatCalendar(fechaFinal);
    } else {
      fechaFinal = null;
    }

    if (fechaInicio !== null && fechaFinal === null) {
      this.resourcesService.openSnackBar(`Ocurrió un error al obtener el rango de fechas.`);
      return;
    }
    if (fechaInicio === null && fechaFinal !== null) {
      this.resourcesService.openSnackBar(`Ocurrió un error al obtener el rango de fechas.`);
      return;
    }

    const REQUEST_SEARCH: RequestSearch = {
      'WORKFLOW': nombreWorkflow,
      'EJECUCION_WORKFLOW': numeroEjecucionWorkflow,
      'ESTADO_WORKFLOW': estadoEjecucionWorkflow,
      'TAREA': nombreTarea,
      'EJECUCION_TAREA': numeroEjecucionTarea,
      'ESTADO_TAREA': estadoEjecucionTarea,
      'PROCESO': nombreProceso,
      'FECHA_INICIO': fechaInicio,
      'FECHA_FINAL': fechaFinal,
      'USUARIO': this.resourcesService.getUser(),
      'NUMERO_LINEA': this.resourcesService.getLineNumber(),
    }

    await lastValueFrom(this._processManagementService.searchRequestWorkflow(REQUEST_SEARCH)).then(
      (responseData: ResponseDataFilterRequest) => {
        if (!responseData.error) {
          this._dialogReg.close(responseData.response);
        } else {
          this.resourcesService.openSnackBar(`${responseData.msg}`);
        }
      }, (httpErrorResponse: HttpErrorResponse) => this.resourcesService.checkErrors(httpErrorResponse)
    );

    this.isLoading = false;
  }
}
