import { Component, ViewChild, OnInit, AfterViewInit } from '@angular/core';
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 { EncService } from 'src/app/services/enc/enc.service';
import { ContentArtitle, DataTableResponse, DialogModule, ResponseDataLine } from 'src/app/interfaces/acquisition-management/artitle.interface';
import { ObjectRequestLine } from 'src/app/interfaces/acquisition-management/order.interface';
import { AlertData } from 'src/app/interfaces/alert.interface';
import { MatDialog } from '@angular/material/dialog';
import { AlertComponent } from 'src/app/components/resources/dialogs/alert/alert.component';
import { ResourcesService } from 'src/app/services/resources/resources.service';
import { lastValueFrom } from 'rxjs';
import { HttpErrorResponse } from '@angular/common/http';
import { OrderService } from 'src/app/services/acquisition-management/order.service';
import { ViewDetailsLineComponent } from '../view-details-line/view-details-line.component';
import { SliderData } from 'src/app/interfaces/slider.interface';
import { PreventiveMaintenanceService } from 'src/app/services/preventive-maintenance.service';
import { PreventiveWorkOrdersActive, PreventiveWorkOrdersActiveResponse } from 'src/app/interfaces/preventive-work-orders-active.interface';
import { PurchasePurpose } from 'src/app/interfaces/acquisition-management/purchase-purpose.interface';
import { UsersProfilesService } from 'src/app/services/users-profiles.service';
import { SocketService } from 'src/app/services/socket.service';
import { UserConsultResponse } from 'src/app/interfaces/user.interface';
import { ProfileInterface } from 'src/app/interfaces/profile.interface';
import { PermissionsData } from '../../../acquisition-management.component';

@Component({
  selector: 'app-shopping-cart',
  templateUrl: './shopping-cart.component.html',
  styleUrls: ['./shopping-cart.component.css']
})
export class ShoppingCartComponent implements AfterViewInit, OnInit {

  // Variable loading
  public isLoading: boolean;
  public isLoadingForm: boolean;

  // Variables de la tabla
  @ViewChild(MatPaginator) paginator!: MatPaginator;
  @ViewChild(MatSort) sort!: MatSort;
  public dataSource: MatTableDataSource<DataTableResponse>;
  
  public displayedColumns: Array<string>;
  public arrShoppingCart: Array<ContentArtitle>;
  public arrPreventiveMaintenance: Array<PreventiveWorkOrdersActive>;
  public arrCorrectiveMaintenance: Array<any>;

  public purchasePurpose: PurchasePurpose;

  public titleCard:string;
  public selectedProject: string;

  public cartShoppingEnabled: boolean;
  public createGroupEnable: boolean;
  public selectedArtitleEnable: boolean;

  constructor(
    public resourcesService: ResourcesService,
    private _router: Router,
    private _encService: EncService,
    private _orderServices: OrderService,
    private _dialog: MatDialog,
    private _preventiveMaintenanceService: PreventiveMaintenanceService,
    private _activatedRoute: ActivatedRoute,
    private _socketService: SocketService,
    private _usersProfilesSevice: UsersProfilesService,
  ) {
    this.isLoading = false;
    this.isLoadingForm = false;
    this.cartShoppingEnabled = true;
    this.createGroupEnable = true;
    this.selectedArtitleEnable = true;
    this.dataSource = new MatTableDataSource<DataTableResponse>([]);
    this.arrShoppingCart = [];
    this.arrPreventiveMaintenance = [];
    this.arrCorrectiveMaintenance = [];
    this.displayedColumns = [
      'IMAGEN',
      'PROVEEDOR',
      'ARTICULO',
      'MODELO',
      'CODIGO',
      'CANTIDAD',
      'PRECIO',
      'PRECIOTOTAL',
      'ACCIONES'
    ];
    this.purchasePurpose = {} as PurchasePurpose;
    this.selectedProject = '';
    this.titleCard = '';
  }

  async ngOnInit() {
    await this.refreshPermissions();
    await this.setPermissions();
    await this.getInformationShopping();
    await this.getShoppingCart();
    await this.getPreventiveMaintenance();
  }

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

  private async refreshPermissions() {
    this._socketService.refreshPermissions().subscribe(async (profUpdEnc) => {
      let idUser = localStorage.getItem('idusuario')!;
      let usrInfo: UserConsultResponse = await lastValueFrom(this._usersProfilesSevice.getUser(idUser, idUser, 1));
      let currentProfile = await this._encService.decrypt(localStorage.getItem('perfil')!);

      if(parseInt(currentProfile) != usrInfo.response.PERFIL){
        this._router.navigate(['/sam/home']);
      }

      let profileUpdated = await this._encService.decrypt(`${profUpdEnc}`);
      if(profileUpdated == currentProfile){
        let profile = localStorage.getItem('perfil')!;

        await lastValueFrom(this._usersProfilesSevice.getProfile( profile, idUser, 1 )).then(
          (responseData: ProfileInterface) => {
            if (!responseData.error) {
              let modPerm = responseData.response.PERMISOS.permissions.filter(item => item.id == 'S002V01M05GEAD')[0];
              let funPerm = modPerm.children.filter(item => item.id == 'S002V01S01ADQU')[0];
              let panPerm1 = funPerm.children.filter(item => item.id == "S002V01F01NSCO")[0];
              this.cartShoppingEnabled = panPerm1.children.filter(item => item.id == 'S002V01P04BOLS')[0].access > 0;
              this.selectedArtitleEnable = panPerm1.children.filter(item => item.id == 'S002V01P03SEAR')[0].access > 0;
              
              let panPerm2 = funPerm.children.filter(item => item.id == "S002V01F02CGPE")[0];
              this.createGroupEnable = panPerm2.children.filter(item => item.id == 'S002V01P01AOCO')[0].access > 0;

              if (panPerm2.access !== 2) {
                this._router.navigate(['/sam/home']);
              }
            } else {
              this.resourcesService.openSnackBar(`${responseData.msg}`);
            }
          }, ( httpErrorResponse: HttpErrorResponse ) => this.resourcesService.checkErrors(httpErrorResponse)
        );
      }
    });
  }

  private async setPermissions() {
    const encPermissions = localStorage.getItem('permisos');
    if (encPermissions === null || encPermissions === undefined || encPermissions === '') {
      this.resourcesService.openSnackBar(`Ocurrió un error al obtener los permisos del usuario.`);
      this._router.navigate(['/sam/home']);
      return;
    }
    const strPermissions:string = await this._encService.decrypt(encPermissions);
    const arrPermissions:Array<PermissionsData> = JSON.parse(strPermissions).permissions;

    let modPerm = arrPermissions.filter(item => item.id == 'S002V01M05GEAD')[0];
    let funPerm = modPerm.children.filter(item => item.id == 'S002V01S01ADQU')[0];
    let panPerm1 = funPerm.children.filter(item => item.id == "S002V01F01NSCO")[0];
    this.cartShoppingEnabled = panPerm1.children.filter(item => item.id == 'S002V01P04BOLS')[0].access > 0;
    this.selectedArtitleEnable = panPerm1.children.filter(item => item.id == 'S002V01P03SEAR')[0].access > 0;
    
    let panPerm2 = funPerm.children.filter(item => item.id == "S002V01F02CGPE")[0];
    this.createGroupEnable = panPerm2.children.filter(item => item.id == 'S002V01P01AOCO')[0].access > 0;


    if (panPerm2.access === 0) {
      this._router.navigate(['/sam/home']);
    }

  }

  public async getInformationShopping() {
    const encInformation:string = this._activatedRoute.snapshot.paramMap.get('info')!;
    const strInformation:string = await this._encService.decrypt(encInformation);
    this.purchasePurpose = JSON.parse(strInformation);  

    switch (this.purchasePurpose.PROPOSITO) {
      case 'MANT-CORR':
        this.titleCard = ` para Mantenimiento Correctivo #${this.purchasePurpose.ID}`;
      break;
      case 'MANT-PREV':
        this.titleCard = ` para Mantenimiento Preventivo #${this.purchasePurpose.ID}`;
      break;
      case 'NA':
        this.titleCard = ``;
      break;
    }
  }

  public async getShoppingCart() {
    // Se obtiene los datos del localstorage del carrito de compra
    let localStorageCar = localStorage.getItem('car_shopping_artitles');
    // Se valida que la variable se encuentre en el localstorage
    let strItemsCar: string = localStorageCar !== null && localStorageCar !== undefined ? localStorageCar : '';

    if (strItemsCar.length !== 0) {
      // Se desencripta la cadena obtenida por el localstorage
      let strArtitlesSelected: string = await this._encService.decrypt(strItemsCar);
      // Se transforma a un arreglo
      this.arrShoppingCart = JSON.parse(strArtitlesSelected);

      // Se inicializa el arreglo de los artículos del carrito
      let arrCarArtitles: Array<DataTableResponse> = [];
      // Se iteran los productos del carrito
      this.arrShoppingCart.map((shoppingCart: ContentArtitle) => {
        // Se iterea el contenido de los artículos
        shoppingCart.content.map((element: DataTableResponse) => {


          // Se genera el objeto para las tablas
          let arrTable: DataTableResponse = {
            NUMERO_ARTICULO: shoppingCart.idArtitle,
            ARTICULO: shoppingCart.artitle,
            NUMERO_DESC_ARTICULO: shoppingCart.idDescArtitle,
            URL_IMAGEN: shoppingCart.url_imagen[0].image,
            NUMERO_PROVEEDOR: shoppingCart.idProvider,
            NUMERO_INFORMACION: element.NUMERO_INFORMACION,
            MODELO: element.MODELO,
            CODIGO: element.CODIGO,
            CARACTERISTICAS: element.CARACTERISTICAS,
            TIPO_UNIDAD: element.TIPO_UNIDAD,
            CANTIDAD: element.CANTIDAD,
            PRECIO: element.PRECIO,
            MONEDA: element.MONEDA,
            // MANTPREV: null,
            // MANTCORR: null,
            IMAGEN: `${shoppingCart.url_imagen[0].image}`,
          }
          arrCarArtitles.push(arrTable);
        });
      });

      this.dataSource.data = arrCarArtitles;
    }
  }

  public async openDialog( typeDialog: string, dataElement: any = null ) {
    if (typeDialog === 'CREATE') {
      this.alert(typeDialog);
      /* this._dialog.open(DescriptionLineComponent, {
        data: dataElement === null ? '' : dataElement,
        disableClose: true,
        width: '700px',
      }).afterClosed().subscribe((description) => {
        if (description) {
        }
      }); */
    } else if (typeDialog === 'DETAILS') {
      this._dialog.open(ViewDetailsLineComponent, {
        data: dataElement.NUMERO_INFORMACION,
        disableClose: true,
        width: '1200px',
      }).afterClosed().subscribe((description) => {
        if (description) {
          this.alert(typeDialog, description);
        }
      });
    }
  }

  public async goShopping() {

    let strPurchasePurpose:string = JSON.stringify(this.purchasePurpose);
    let encPurchasePurpose:string = await this._encService.encrypt(strPurchasePurpose);
    this._router.navigate([`/sam/GEAD/PROV/SOPR/${ encPurchasePurpose }`]);
  }

  // Método para ejecutar una alerta
  public async alert(type: string, dataElement: any = null!) {
    let dataDialog: AlertData = {} as AlertData;
    if (type === 'DELETE') {
      dataDialog = {
        icon: "warning",
        title: "Eliminar Producto",
        description: "¿Está seguro de eliminar este produto del carrito de compra?"
      };
    }else if(type === 'CREATE'){
      dataDialog = {
        icon: "warning",
        title: "Registro de Línea de Solicitud",
        description: "¿Está seguro de registrar estos productos a la línea de solicitud de compra?"
      };
    }

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

    // Se obtiene la respuesta obtenida por la alerta
    dialogRef.afterClosed().subscribe((result) => {
      // Se ejecuta la acción según el tipo seleccionado
      if (result && type === 'DELETE') {
        // Se ejecuta el método para eliminar una tabla
        this.deleteArtitle(dataElement);
      }
      // Alerta para registrar
      if(result && type === 'CREATE'){
        this.registerRequestLine(dataElement);
      }else if(!result && type === 'CREATE'){
        this.openDialog('CREATE',dataElement);
      }
    });
    this.isLoadingForm = false;
  }

  // Método: Registro de línea de solicitud de compra
  private async registerRequestLine(description: string) {
    this.isLoading = true;
    
    let arrRequestLine: Array<GetRequestLine> = await this.getPurchaseLine(this.dataSource.data);    
    let objRequestLine: ObjectRequestLine = {
      LINE: this.resourcesService.getLineNumber(),
      USER: this.resourcesService.getUser(),
      PRODUCTS: arrRequestLine,
      PURPOSE: this.purchasePurpose,
    }
    
    await lastValueFrom(this._orderServices.createRequestLine(objRequestLine)).then(
      (data: ResponseDataLine) => {
        if (!data.error) {
          this.resourcesService.openSnackBar('¡La línea de solicitud se registró correctamente!');
          // this.resourcesService.openSnackBarAfter('La solicitud se encontrará el proceso de validación por el módulo de Gestión de Presupuesto');
          localStorage.removeItem('car_shopping_artitles');
          this._router.navigate(['/sam/GEAD/ADQU/NSCO']);
        } else {
          this.resourcesService.openSnackBar('Ocurrió un error inesperado: ' + data.msg);
        }
      }, (error: HttpErrorResponse) => {
        this.resourcesService.checkErrors(error);
      }
    );
    this.isLoading = false;
  }

  public async getPurchaseLine( arrArtitleCar:Array<DataTableResponse> ) {
    let arrPurchaseLine: Array<GetRequestLine> = [];
    let arrProviders: Array<string> = [];
    arrArtitleCar.map((artitle: DataTableResponse) => {
      if( !arrProviders.includes(artitle.NUMERO_PROVEEDOR) ){
        arrProviders.push(artitle.NUMERO_PROVEEDOR);
      }
    });

    arrProviders.map((provider:string, index: number) => {
      let arrInformation: any = [];
      arrArtitleCar.map((artitle: DataTableResponse) => {
        if (provider === artitle.NUMERO_PROVEEDOR) {
          arrInformation.push({
            CANTIDAD: artitle.CANTIDAD,
            CARACTERISTICAS: artitle.CARACTERISTICAS,
            CODIGO: artitle.CODIGO,
            MODELO: artitle.MODELO,
            MONEDA: artitle.MONEDA,
            NUMERO_ARTICULO: artitle.NUMERO_ARTICULO,
            NUMERO_INFORMACION: artitle.NUMERO_INFORMACION,
            PRECIO: artitle.PRECIO,
          });
        }
      });

      arrPurchaseLine.push({
        PROVIDER: provider,
        ARTITLES: arrInformation,
      });
    });

    return arrPurchaseLine;
  }

  // Método: Eliminar artículo
  public async deleteArtitle(artitle: DataTableResponse) {
    // Se inicializa el index del carrito en caso de ya no existir contenido
    let indexShoppingCart: number = null!;

    // Se iteran los prodcutos del carrito
    this.arrShoppingCart.map((shoppingCar: ContentArtitle, indexShopping: number) => {
      // Se identifica el artículo seleccionado
      if (shoppingCar.idArtitle === artitle.NUMERO_ARTICULO) {
        // Se obtiene el contenido del artículo
        let arrContentCart: Array<DataTableResponse> = shoppingCar.content;
        // Se itera el contenido de los artículos
        arrContentCart.map((contentCart: DataTableResponse, indexContentCart: number) => {
          // Se identifica el producto del contenido del artículo
          if (contentCart.NUMERO_INFORMACION === artitle.NUMERO_INFORMACION) {
            // Se elimina el producto seleccionado
            shoppingCar.content.splice(indexContentCart, 1);
          }
        });
      }
      // En caso de ya no haber contenidos en el artículo entonces se guarda el index del artículo
      if (shoppingCar.content.length === 0) {
        indexShoppingCart = indexShopping;
      }
    });

    // Si el index del carrito es diferente a null entonces significa que ya no hay contenidos en el artículo en el carrito
    if (indexShoppingCart !== null) {
      // Se elimina el artículo mediante el index
      this.arrShoppingCart.splice(indexShoppingCart, 1);
    }

    // El carrito se transforma en una cadena
    let strShoppingCart = JSON.stringify(this.arrShoppingCart);
    // La cadena se encripta
    let encShoppingCart = await this._encService.encrypt(strShoppingCart);
    // La cadena encriptada se guarda en el localstorage
    localStorage.setItem('car_shopping_artitles', encShoppingCart);
    // Se actualiza el carrito de compra
    this.getShoppingCart();
  }


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

  public getTotalCost() {
    return this.dataSource.data.map(t => t.PRECIO * t.CANTIDAD).reduce((acc, value) => acc + value, 0);
  }

  private async getPreventiveMaintenance() {
    this.isLoading = true;
    const idUser:string = this.resourcesService.getUser();
    const line:number = parseInt(this.resourcesService.getLineNumber());
    await lastValueFrom(this._preventiveMaintenanceService.getActiveWorkOrders(idUser, line)).then(
      (responseData: PreventiveWorkOrdersActiveResponse) => {
        if ( !responseData.error ) {
          this.arrPreventiveMaintenance = responseData.response;
        } else {
          this.resourcesService.openSnackBar(responseData.msg);
        }
      },(error: HttpErrorResponse) => this.resourcesService.checkErrors(error)
    );
    this.isLoading = false;
  }

}



export interface GetRequestLine {
  PROVIDER: string;
  ARTITLES: Array<GetArtitleCar>
}

export interface RequestLine {
  ARTICULO: string;
  CANTIDAD: number;
  CARACTERISTICAS: string;
  CODIGO: string;
  IMAGEN: string;
  MODELO: string;
  MONEDA: string;
  NUMERO_ARTICULO: number;
  NUMERO_DESC_ARTICULO: number;
  NUMERO_INFORMACION: number;
  PRECIO: number;
  URL_IMAGEN: Array<SliderData>;
}

export interface GetArtitleCar {
  ARTICULO: string;
  CANTIDAD: number;
  CARACTERISTICAS: string;
  CODIGO: string;
  IMAGEN: string;
  MODELO: string;
  MONEDA: string;
  NUMERO_ARTICULO: number;
  NUMERO_DESC_ARTICULO: number;
  NUMERO_INFORMACION: number;
  NUMERO_PROVEEDOR: string;
  PRECIO: number;
  URL_IMAGEN: Array<string>;
}
