import { HttpErrorResponse } from '@angular/common/http';
import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { ActivatedRoute, Router } from '@angular/router';
import { lastValueFrom } from 'rxjs';
import { AlertComponent } from 'src/app/components/resources/dialogs/alert/alert.component';
import { DetailsProduct, GroupRequestLine, ResponseDataRequestLines } from 'src/app/interfaces/acquisition-management/acquisition/order.interface';
import { ResponseDataDispatch } from 'src/app/interfaces/acquisition-management/dispatch/dispatch.interface';
import { AlertData } from 'src/app/interfaces/alert.interface';
import { DispatchService } from 'src/app/services/acquisition-management/acquisition/dispatch.service';
import { OrderService } from 'src/app/services/acquisition-management/acquisition/order.service';
import { EncService } from 'src/app/services/enc/enc.service';
import { ResourcesService } from 'src/app/services/resources/resources.service';
import { ConfigGroupComponent } from '../config-group/config-group.component';
import { InfoGroupComponent } from '../info-group/info-group.component';

@Component({
  selector: 'app-group-line',
  templateUrl: './group-request-line.component.html',
  styleUrls: ['./group-request-line.component.css']
})
export class GroupRequestLineComponent implements AfterViewInit, OnInit {

  public isLoading: boolean;
  public isLoadingForm: boolean;

  public btnSmall: boolean;
  public card_size: string;

  public txtBuscador:string;


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

  private idRequestLine: string;
  public responseRequestLine: ResponseDataRequestLines;

  constructor(
    private _dialog: MatDialog,
    private _activatedRouter: ActivatedRoute,
    private _resourcesService: ResourcesService,
    private _router: Router,
    private _encService: EncService,
    private _orderService: OrderService,
    private _distpachService: DispatchService,
  ) {
    this.card_size = 'card-size-normal mat-elevation-z8';
    this.displayedColumns = [ 'INDEX', 'PROVEEDOR', 'PRODUCTOS', 'PRECIO_TOTAL', 'FECHA_REGISTRA', 'USUARIO_REGISTRA', 'DESPACHO', /* 'METODO', */ 'PROPOSITO', 'ACCIONES' ];
    this.dataSource = new MatTableDataSource();
    this.isLoading = false;
    this.isLoadingForm = false;
    this.btnSmall = false;
    this.idRequestLine = '';
    this.responseRequestLine = {} as ResponseDataRequestLines;
    this.txtBuscador = '';
    this.getIdRequestLine();
  }

  ngOnInit(): void {
  }

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

  private async getIdRequestLine() {
    try {
      this.isLoading = true;
      // Se obtiene el identificador del id de la solicitud encriptado
      let encIdRequestLine: string = this._activatedRouter.snapshot.paramMap.get('idRequestLine')!;

      this.idRequestLine = await this._encService.desencriptar(encIdRequestLine);

      // Se verifica que los ID sean válidos
      if (encIdRequestLine !== '' && encIdRequestLine !== null) {
        // Se obtiene el artículo seleccionado mediante los ID del artículo y el proveedor
        this.responseRequestLine = await this.getRequestLine(encIdRequestLine);
        this.groupRequestLine(this.responseRequestLine.response.PRODUCTOS);

      } else {
        this._resourcesService.openSnackBar('Ocurrió un error al obtener el identificador del artículo y/o proveedor, intentelo nuevamente.');
        this._router.navigate(['/sam/orders']);
        this.isLoading = false;
      }
    } catch (error: any) {
      this._resourcesService.openSnackBar('Ocurrió al desencriptar el identificador del artículo y/o proveedor.');
      this._router.navigate(['/sam/orders']);
      this.isLoading = false;
    }
  }

  private async getRequestLine(idRequestLine: string): Promise<ResponseDataRequestLines> {
    return await lastValueFrom(this._orderService.getRequestLine(idRequestLine));
  }


  private async getDistpach(){
    this.isLoadingForm = true;
    return await lastValueFrom(this._distpachService.getAllDistpach()).then(
      (responseData: ResponseDataDispatch) => {
        this.isLoadingForm = false;
        return responseData.response;

      },(error: HttpErrorResponse) => this._resourcesService.checkErrors(error)
    );

  }

  // Método para realizar los grupos de la solicitud de compra
  private groupRequestLine(arrRequestLine: Array<DetailsProduct>) {
    // Se obtienen los proveedores
    let arrProviders: Array<string> = [...new Set(arrRequestLine.map((item: DetailsProduct) => item.NUMERO_PROVEEDOR))];

    // Se inicializa el arreglo que contendran los grupos
    let arrGroupRequest: Array<GroupRequestLine> = [];

    // Se iteran los proveedores de la solicitud
    arrProviders.forEach((idProvider: string) => {

      // Se iteran los productos de la solicitud
      arrRequestLine.forEach((requestLine: DetailsProduct) => {

        // Se comprueba que el producto coincida con su proveedor
        if (idProvider === requestLine.NUMERO_PROVEEDOR) {
          // Si la variable que contendrá los grupos aún no tiene ningún registro
          if (arrGroupRequest.length === 0) {

            // Se ingresan las variables que contendrá el grupo
            let groupRequest:GroupRequestLine = {
              NUMERO_PROVEEDOR: requestLine.NUMERO_PROVEEDOR,
              PROVEEDOR: requestLine.PROVEEDOR,
              PRECIO_TOTAL: requestLine.PRECIO_TOTAL,
              FECHA_REGISTRA: requestLine.FECHA_REGISTRA,
              FECHA_MODIFICA: requestLine.FECHA_MODIFICA,
              USUARIO_REGISTRA: requestLine.USUARIO_REGISTRA,
              USUARIO_MODIFICA: requestLine.USUARIO_MODIFICA,
              DESPACHO: '',
              METODO_PAGO: '',
              PROPOSITO: '',
              PRODUCTOS: [],
            };

            // Se ingresa el objeto que contendrá el producto hacia el grupo
            let objProduct:DetailsProduct = {
              NUMERO_ARTI_SELE: requestLine.NUMERO_ARTI_SELE,
              NUMERO_ARTICULO: requestLine.NUMERO_ARTICULO,
              NUMERO_PRODUCTO: requestLine.NUMERO_PRODUCTO,
              MODELO: requestLine.MODELO,
              CODIGO: requestLine.CODIGO,
              CARACTERISTICAS: requestLine.CARACTERISTICAS,
              CANTIDAD: requestLine.CANTIDAD,
              PRECIO_UNITARIO: requestLine.PRECIO_UNITARIO,
              PRECIO_TOTAL: requestLine.PRECIO_TOTAL,
              ESTADO: requestLine.ESTADO,
              USUARIO_REGISTRA: requestLine.USUARIO_REGISTRA,
              FECHA_REGISTRA: requestLine.FECHA_REGISTRA,
              USUARIO_MODIFICA: requestLine.USUARIO_MODIFICA,
              FECHA_MODIFICA: requestLine.FECHA_MODIFICA,
              NUMERO_PROVEEDOR: requestLine.NUMERO_PROVEEDOR,
              PROVEEDOR: requestLine.PROVEEDOR,
            }

            // Se agrega el producto al grupo
            groupRequest.PRODUCTOS.push(objProduct);
            // El grupo de guarda
            arrGroupRequest.push(groupRequest);
          } else {
            // Si la variable de los grupos ya tiene datos entonces...

            // Se inicializa la variabla para dererminar si ya fue agregado el grupo en caso de ya estar registrado
            let isAdded = false;

            // Se iteran los grupos agregados
            arrGroupRequest.forEach((groupRequest: any) => {

              // Si el proveedor ya existe en el grupo, entonces..
              if (idProvider === groupRequest.NUMERO_PROVEEDOR) {
                // Se incrementa el precio total en el grupo con el nuevo producto agregado
                groupRequest.PRECIO_TOTAL = requestLine.PRECIO_TOTAL + groupRequest.PRECIO_TOTAL;

                // Se ingresa el objeto que contendrá el producto hacia el grupo
                let objProduct:DetailsProduct = {
                  NUMERO_ARTI_SELE: requestLine.NUMERO_ARTI_SELE,
                  NUMERO_ARTICULO: requestLine.NUMERO_ARTICULO,
                  NUMERO_PRODUCTO: requestLine.NUMERO_PRODUCTO,
                  MODELO: requestLine.MODELO,
                  CODIGO: requestLine.CODIGO,
                  CARACTERISTICAS: requestLine.CARACTERISTICAS,
                  CANTIDAD: requestLine.CANTIDAD,
                  PRECIO_UNITARIO: requestLine.PRECIO_UNITARIO,
                  PRECIO_TOTAL: requestLine.PRECIO_TOTAL,
                  ESTADO: requestLine.ESTADO,
                  USUARIO_REGISTRA: requestLine.USUARIO_REGISTRA,
                  FECHA_REGISTRA: requestLine.FECHA_REGISTRA,
                  USUARIO_MODIFICA: requestLine.USUARIO_MODIFICA,
                  FECHA_MODIFICA: requestLine.FECHA_MODIFICA,
                  NUMERO_PROVEEDOR: requestLine.NUMERO_PROVEEDOR,
                  PROVEEDOR: requestLine.PROVEEDOR,
                }

                // Se agrega el producto al grupo
                groupRequest.PRODUCTOS.push(objProduct);

                // La variable se cambia a verdadero, ya que el grupo ya fue agregado
                isAdded = true;
              }
            });

            // Se identifica si el grupo ya fue agregado o no
            if (!isAdded) {
              // En caso de no ser agregado entonces...

               // Se ingresan las variables que contendrá el grupo
              let groupRequest:GroupRequestLine = {
                NUMERO_PROVEEDOR: requestLine.NUMERO_PROVEEDOR,
                PROVEEDOR: requestLine.PROVEEDOR,
                PRECIO_TOTAL: requestLine.PRECIO_TOTAL,
                FECHA_REGISTRA: requestLine.FECHA_REGISTRA,
                FECHA_MODIFICA: requestLine.FECHA_MODIFICA,
                USUARIO_REGISTRA: requestLine.USUARIO_REGISTRA,
                USUARIO_MODIFICA: requestLine.USUARIO_MODIFICA,
                DESPACHO: '',
                METODO_PAGO: '',
                PROPOSITO: '',
                PRODUCTOS: [],
              };

              // Se ingresa el objeto que contendrá el producto hacia el grupo
              let objProduct:DetailsProduct = {
                NUMERO_ARTI_SELE: requestLine.NUMERO_ARTI_SELE,
                NUMERO_ARTICULO: requestLine.NUMERO_ARTICULO,
                NUMERO_PRODUCTO: requestLine.NUMERO_PRODUCTO,
                MODELO: requestLine.MODELO,
                CODIGO: requestLine.CODIGO,
                CARACTERISTICAS: requestLine.CARACTERISTICAS,
                CANTIDAD: requestLine.CANTIDAD,
                PRECIO_UNITARIO: requestLine.PRECIO_UNITARIO,
                PRECIO_TOTAL: requestLine.PRECIO_TOTAL,
                ESTADO: requestLine.ESTADO,
                USUARIO_REGISTRA: requestLine.USUARIO_REGISTRA,
                FECHA_REGISTRA: requestLine.FECHA_REGISTRA,
                USUARIO_MODIFICA: requestLine.USUARIO_MODIFICA,
                FECHA_MODIFICA: requestLine.FECHA_MODIFICA,
                NUMERO_PROVEEDOR: requestLine.NUMERO_PROVEEDOR,
                PROVEEDOR: requestLine.PROVEEDOR,
              }

              // Se agrega el producto al grupo
              groupRequest.PRODUCTOS.push(objProduct);

              // El grupo de guarda
              arrGroupRequest.push(groupRequest);
            }
          }
        }
      });
    });

    this.dataSource.data = arrGroupRequest;
    this.isLoading = false;
  }

  // Método para ejecutar una alerta
  public async alert(type: string, dataElement: any = null) {
    this.isLoadingForm = true;
    let dataDialog: AlertData = {} as AlertData;
    if (type === 'CANCEL') {
      dataDialog = {
        icon: "warning",
        title: "Cancelar Solicitud",
        description: "¿Está seguro de cancelar la línea de solicitud de compra?"
      };
    }

    // Se ejecuta la alerta
    const dialogRef = this._dialog.open(AlertComponent, {
      data: dataDialog,
      disableClose: true,
      width: '350px',
    });

    // Se obtiene la respuesta obtenida por la alerta
    dialogRef.afterClosed().subscribe((result) => {
      if (result && type === 'CANCEL') {

      }
    });
    this.isLoadingForm = false;
  }

  public async openDialog(type: string, dataElement: any = null) {
    if(type === 'DETAILS'){
      this._dialog.open(InfoGroupComponent, { data: dataElement, disableClose: true, width: '1300px', });
    }else if(type === 'CONFIG'){
      let arrDispatch = await this.getDistpach();
      this._dialog.open(ConfigGroupComponent, {
        data: arrDispatch,
        disableClose: true, width: '400px',
      }).afterClosed().subscribe((result) => {
        if (result) {

        }
      });
    }
  }

  // Método para regresar a la pantalla anterior
  public goBack() {
    window.history.back();
  }

  // Método de filtrado de datos
  public applyFilter(event: any, type: string) {
    let filterValue:string;
    if (type == 'INP') {
      filterValue = (event.target as HTMLInputElement).value;
    }else{
      this.txtBuscador = event;
      filterValue = event;
    }
    this.dataSource.filter = filterValue.trim().toLowerCase();
    if (this.dataSource.paginator) {
      this.dataSource.paginator.firstPage();
    }
  }

  // Método para reajustar los botones según sus dimensiones
  public onResize() {
    this.btnSmall = window.innerWidth <= 1405;
  }

  public formatDate(dateRegister:string, dateUpdate:string | null):string {
    let date:string = (dateUpdate === null) ? dateRegister : dateUpdate;
    let arrDateTime:Array<string> = date.split(' ');
    let arrDate:Array<string> = arrDateTime[0].split('-');
    return `${arrDate[2]}-${arrDate[1]}-${arrDate[0]} ${arrDateTime[1]}`;
  }
}
