import {
  Component,
  Inject,
  OnInit,
  ViewChild,
  AfterViewInit,
} from '@angular/core';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatTableDataSource } from '@angular/material/table';
import { ActivatedRoute, NavigationExtras, Router } from '@angular/router';
import { MatDialog } from '@angular/material/dialog';
import { WorkflowPasosFormComponent } from './workflow-tasks-form/workflow-pasos-form.component';
import { TranslationComponent } from '../../resources/translation/translation.component';
import { TranslateService } from '@ngx-translate/core';
import { WorkflowService } from 'src/app/services/samwf/workflow.service';
import { TaskInterface } from 'src/app/interfaces/samwf/task-interface';
import { TasksJSONInterface } from 'src/app/interfaces/samwf/tasks-json-interface';
import { last, lastValueFrom, takeLast } from 'rxjs';
import { MatSnackBar } from '@angular/material/snack-bar';
import { ResponseData } from 'src/app/interfaces/response-data';
import { WorkflowUsersComponent } from './workflow-users/workflow-users.component';
import { WorkflowFieldsFormComponent } from './workflow-fields-form/workflow-fields-form.component';
import { ResourcesService } from 'src/app/services/resources/resources.service';
import { MatSort } from '@angular/material/sort';
import { AlertComponent } from '../../resources/dialogs/alert/alert.component';
import { AlertData } from 'src/app/interfaces/alert.interface';
import { MgadService } from 'src/app/services/mgad/mgad.service';
import { HttpErrorResponse } from '@angular/common/http';

@Component({
  selector: 'app-workflow-detail',
  templateUrl: './workflow-detail.component.html',
  styleUrls: ['./workflow-detail.component.css'],
})
export class WorkflowDetailComponent implements AfterViewInit {
  displayedColumns: string[] = [
    'sequence',
    'process',
    'estatus',
    'notification',
    'actions',
  ];
  data_empty = false;

  workflow: any = {};
  workflowObject: any = {};
  tasks: any = [];
  idWorkflow: any;
  arrAux: any[] = [];
  formDataService: any[] = [];
  public dataSource: MatTableDataSource<any>;

  public isLoading: boolean = true;
  public isLoadingForm: boolean = false;

  // ---- SmartPage ----
  public btnSmall: boolean = false;
  public card_size = 'card-size-normal mat-elevation-z8';

  @ViewChild(MatPaginator) paginator!: MatPaginator;
  @ViewChild(MatSort) sort!: MatSort;

  constructor(
    private router: ActivatedRoute,
    public dialog: MatDialog,
    private routerNavigate: Router,
    private translate: TranslateService,
    private _samwfService: WorkflowService,
    private _snackBar: MatSnackBar,
    private _resourceService: ResourcesService,
    private _mgadService: MgadService
  ) {
    this.idWorkflow = this.router.snapshot.paramMap.get('id');
    this.dataSource = new MatTableDataSource();
    translate.setDefaultLang('es');
    this.getTasksWorkflow();
  }

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

    if (window.innerWidth <= 990) {
      this.btnSmall = true;
      this.card_size = 'card-size-small';
    } else if (window.innerWidth > 990) {
      this.btnSmall = false;
      this.card_size = 'card-size-normal mat-elevation-z8';
    }

    this.translate.get('paginador').subscribe((data: any) => {
      this.dataSource.paginator = this.paginator;
      this.paginator._intl.itemsPerPageLabel = data[0];
      this.paginator._intl.firstPageLabel = data[1];
      this.paginator._intl.lastPageLabel = data[2];
      this.paginator._intl.nextPageLabel = data[3];
      this.paginator._intl.previousPageLabel = data[4];
    });
  }

  ngOnInit(): void {}

  openDialogsByType(action: string, item: any = {}) {
    if (this.workflowObject.isForm == true) {
      this.openDialogFieldsForm(action, item);
    } else {
      this.openDialogTaskForm(action, item);
    }
  }

  // Dialogo
  async openDialogTaskForm(action: string, item: any = {}) {
    const sleep = (ms: number) =>
      new Promise((resolve) => setTimeout(resolve, ms));

    let processArr: any[] = [];

    await lastValueFrom(this._samwfService.getTasks()).then(
      (data: any) => {
        /* processArr = data.response;
         */ processArr = data.response.filter((object: any) => {
          return object.id != 1 && object.id != 2;
        });
      },
      (error: HttpErrorResponse) => {
        this._resourceService.checkErrors(error);
      }
    );

    let data = item != null ? JSON.stringify(item) : null;
    let tasks_bd = processArr;
    this.sendArrayTasks(null);

    this.sendArrayTasks(processArr);
    if (action == 'Registrar') {
      this.routerNavigate.navigate([
        `sam/workflow/${this.idWorkflow}/tasksFlow`,
        { data, action },
      ]);
    } else {
      this.routerNavigate.navigate([
        `sam/workflow/${this.idWorkflow}/tasksFlowEdit`,
        { data, action },
      ]);
    }
  }

  async openDialogFieldsForm(action: string, item: any) {
    const sleep = (ms: number) =>
      new Promise((resolve) => setTimeout(resolve, ms));
    let dialogRef: any;

    this.getFormByID(this.workflowObject.id_form, action);
    await sleep(300);

    if (action == 'Modificar') {
      this.formDataService.push(item);
    }

    this.isLoadingForm = true;
    let dataAction = {
      action: action,
      item: item,
      fields: this.formDataService,
    };

    if (this.formDataService.length > 0) {
      dialogRef = this.dialog.open(WorkflowFieldsFormComponent, {
        data: dataAction,
        width: '800px',
        disableClose: true,
      });

      dialogRef.afterClosed().subscribe((result: any) => {
        if (result) {
          if (action == 'Registrar') {
            this.formatSequence(result);
          } else {
            this.modifyField(result, item);
          }
        }
        this.isLoadingForm = false;
      });
    } else {
      this.isLoadingForm = false;
      this._snackBar.open(
        'Todos los campos del formulario, fueron registrados',
        'Cerrar'
      );
    }
  }

  private formatSequence(result: any) {
    if (this.workflow.length == 0) {
      result.sequence = 1;
      this.arrAux.push(result);
      this.workflow.push(result);
    } else {
      this.workflow.push(result);
      for (let index = 0; index < this.workflow.length; index++) {
        this.workflow[index].sequence = index + 1;
        this.workflow[index].nextSequence =
          index + 1 == this.workflow.length
            ? null
            : this.workflow[index].sequence + 1;
      }
    }

    this.workflowObject.fields = this.workflow;
    this.dataSource.data = this.workflow;

    this.asingTaskWorkflow();
  }

  private modifyField(field: any, item: any) {
    let positionToModify = this.workflow.findIndex((object: any) => {
      return object.sequence == field.sequence;
    });

    this.workflowObject.fields[positionToModify] = field;
    this.asingTaskWorkflow();
  }

  openDialogUsers(item: any) {
    this.isLoadingForm = true;
    let dataAction = {
      action: 'Usuarios',
      item: item,
    };

    const dialogRef = this.dialog.open(WorkflowUsersComponent, {
      data: dataAction,
    });

    dialogRef.afterClosed().subscribe((result) => {
      this.isLoadingForm = false;
    });
  }

  sendArrayTasks(data: any) {
    this._samwfService.setArray(data);
  }

  backToWorkflows() {
    this.routerNavigate.navigate(['sam/workflow']);
  }

  public async alert(type: string, data: any = null, index: any) {
    this.isLoadingForm = true;
    let info: AlertData = {} as AlertData;
    switch (type) {
      case 'ELT':
        info = {
          icon: 'warning',
          title: 'Eliminar tarea',
          description: '¿Está seguro de eliminar la tarea?',
        };
        break;
      case 'DT':
        info = {
          icon: 'warning',
          title:
            data.isAvailable == true ? 'Inhabilitar tarea' : 'Habilitar tarea',
          description:
            data.isAvailable == true
              ? '¿Está seguro de inhabilitar la tarea?'
              : '¿Está seguro de habilitar la tarea?',
        };
    }

    const dialogRef = this.dialog.open(AlertComponent, {
      data: info,
      disableClose: true,
      width: '350px',
    });

    dialogRef.afterClosed().subscribe((result) => {
      if (result) {
        switch (type) {
          case 'ELT':
            this.deleteTask(data, index);
            break;
          case 'DT':
            this.disableTask(data.sequence);
            break;
        }
      }
      this.isLoadingForm = false;
    });
  }

  showDiagram() {
    this.router.params.subscribe((params) => {
      this.routerNavigate.navigate(['sam/workflow/diagrama/', params['id']]);
    });
  }

  deleteTask(task: any, indexTask: any) {
    let contIsChild = false;
    let filterFlow: any[] = [];
    let filterFlowAux: any[] = [];
    let positionTaskChangeSequence = this.dataSource.data.findIndex(
      (object: any) => {
        return object.sequence === task.changeSequence;
      }
    );

    filterFlow = this.dataSource.data.filter((object: any) => {
      return (
        object.sequence >= task.nextSequence &&
        object.sequence <= task.changeSequence
      );
    });

    for (let index = 0; index < this.dataSource.data.length; index++) {
      if (
        positionTaskChangeSequence > -1 &&
        this.dataSource.data[positionTaskChangeSequence].changeSequence != null
      ) {
        if (
          this.dataSource.data[index].sequence ==
          this.dataSource.data[positionTaskChangeSequence].changeSequence
        ) {
          positionTaskChangeSequence = index;
          if (
            positionTaskChangeSequence > -1 &&
            this.dataSource.data[positionTaskChangeSequence].changeSequence !=
              null
          ) {
            if (
              this.dataSource.data[index].sequence ==
              this.dataSource.data[positionTaskChangeSequence].changeSequence
            ) {
              positionTaskChangeSequence = index;
            }
          }
        }
      }
    }

    if (positionTaskChangeSequence > -1) {
      filterFlowAux = this.dataSource.data.filter((object: any) => {
        return (
          object.sequence > task.changeSequence &&
          object.sequence <=
            this.dataSource.data[positionTaskChangeSequence].sequence
        );
      });

      filterFlow = filterFlow.concat(filterFlowAux);
    }

    filterFlow.push(task);

    for (let index = 0; index < this.dataSource.data.length; index++) {
      if (
        this.dataSource.data[index].nextSequence == task.sequence &&
        this.dataSource.data[index].isConditional == true
      ) {
        contIsChild = true;
      } else if (
        this.dataSource.data[index].changeSequence == task.sequence &&
        this.dataSource.data[index].isConditional == true
      ) {
        contIsChild = true;
      }
    }

    if (contIsChild == false) {
      const deleteTasks = filterFlow;
      this.filterLevel1(deleteTasks, filterFlow);
    } else {
      this._resourceService.openSnackBar(
        'No se puede eliminar una tarea hija',
        'cerrar',
        5000
      );
    }
  }

  private filterLevel1(deleteTasks: any[], filterFlow: any[]) {
    for (let index = 0; index < filterFlow.length; index++) {
      let positionDelete = this.dataSource.data.findIndex((object: any) => {
        return object.sequence == filterFlow[index].sequence;
      });

      this.dataSource.data = this.dataSource.data.filter(
        (i: any) => i != this.dataSource.data[positionDelete]
      );
    }

    for (let index = 0; index < deleteTasks.length; index++) {
      let positionDelete = this.dataSource.data.findIndex((object: any) => {
        return object.nextSequence == deleteTasks[index].sequence;
      });

      let positionDeleteChange = this.dataSource.data.findIndex(
        (object: any) => {
          return object.changeSequence == deleteTasks[index].sequence;
        }
      );

      if (positionDelete > -1) {
        this.dataSource.data[positionDelete].nextSequence =
          deleteTasks[index].sequence;
      } else if (positionDeleteChange > -1) {
        this.dataSource.data[positionDeleteChange].changeSequence =
          deleteTasks[index].sequence;
      }
    }

    this.filterLevel2();
  }

  private filterLevel2() {
    for (let index = 0; index < this.dataSource.data.length; index++) {
      if (
        this.dataSource.data[index].sequence !== 1000 &&
        this.dataSource.data[index].nextSequence !=
          this.dataSource.data[index + 1].sequence
      ) {
        this.dataSource.data[index].nextSequence =
          this.dataSource.data[index + 1].sequence;
        this.dataSource.data[index].sequence == null;
      }
    }

    if (this.dataSource.data.length > 2) {
      this.workflowObject.tasks = this.dataSource.data;
      this.asingTaskWorkflow();
    } else {
      this.dataSource.data = this.workflow;

      this._snackBar.open(
        'La tarea no puede ser eliminada, ya que el workflow debe contar con 3 tareas minimo ',
        'Cerrar',
        {
          duration: 3000,
        }
      );
    }
  }

  async disableTask(sequence: any) {
    let taskAux = {
      sequence: sequence,
      id_workflow: parseInt(this.idWorkflow),
    };

    await lastValueFrom(this._samwfService.disableTaskWorklfow(taskAux)).then(
      (data: ResponseData) => {
        if (!data.error) {
          this.ngOnInit();
          this._snackBar.open('!Actualización de tarea exitoso!', 'Cerrar', {
            duration: 3000,
          });
        }
      },
      (error: HttpErrorResponse) => {
        this._resourceService.checkErrors(error);
      }
    );
    this.getTasksWorkflow();
  }

  private async getTasksWorkflow() {
    this.isLoading = true;
    await lastValueFrom(this._samwfService.getWorkflow(this.idWorkflow)).then(
      (data: any) => {
        this.workflowObject = data.response;
        console.log(data.response);

        if (this.workflowObject.isForm == true) {
          this.workflow = data.response.fields;
          this.dataSource.data =
            data.response.fields.length > 0 ? data.response.fields : [];
        } else {
          this.workflow = data.response.tasks;
          this.dataSource.data = data.response.tasks;

          this.dataSource.data.length > 0
            ? (this.data_empty = false)
            : (this.data_empty = true);
        }
      },
      (error: HttpErrorResponse) => {
        this._resourceService.checkErrors(error);
      }
    );
    this.isLoading = false;
  }

  private async asingTaskWorkflow() {
    await lastValueFrom(
      this._samwfService.updateWorkflow(this.workflowObject, this.idWorkflow)
    ).then(
      (data: ResponseData) => {
        console.log(data);
        this._snackBar.open('!Actualización de workflow exitoso!', 'Cerrar', {
          duration: 3000,
        });
      },
      (error: HttpErrorResponse) => {
        this._resourceService.checkErrors(error);
      }
    );
    this.getTasksWorkflow();
  }

  private async getFormByID(id_form: any, action: any) {
    await lastValueFrom(this._mgadService.getFormsByID(id_form)).then(
      (data: any) => {
        this.formDataService = data.response.FIELDS[0].form;
        let position = -1;

        for (let index = 0; index < this.dataSource.data.length; index++) {
          position = this.formDataService.findIndex((data: any) => {
            return data.id == this.dataSource.data[index].id;
          });

          if (position >= 0) {
            this.formDataService.splice(position, 1);
          }
        }
      },
      (error: HttpErrorResponse) => {
        this._resourceService.checkErrors(error);
      }
    );
  }

  public applyFilter(event: Event) {
    const filterValue = (event.target as HTMLInputElement).value;
    this.dataSource.filter = filterValue.trim().toLowerCase();
    if (this.dataSource.paginator) {
      this.dataSource.paginator.firstPage();
    }
  }

  public onResize(event: any) {
    if (event.target.innerWidth <= 990) {
      this.btnSmall = true;
      this.card_size = 'card-size-small';
    } else if (event.target.innerWidth > 990) {
      this.btnSmall = false;
      this.card_size = 'card-size-normal mat-elevation-z8';
    }
  }
}
