import { Component, ElementRef, HostListener, Inject, Input, OnInit, Renderer2, SimpleChanges} from '@angular/core';
import { CartService } from 'src/app/services/cart/cart.service';
import { Subscription } from 'rxjs';
import { ColumnConfig, searchRenderInterface } from 'src/app/interfaces/common-interfaces';
import { environment } from 'src/environments/environment';
import sortArray from 'sort-array';
import { DOCUMENT } from '@angular/common';
import { SessionService } from 'src/app/services/session/session.service';
import { UtilitiesService } from 'src/app/services/utilities/utilities.service';
import { SessionDataInterface } from 'src/app/interfaces/session-data-interface';
import { DataTransmitterService } from 'src/app/services/dataTransmitter/data-transmitter.service';

@Component({
  standalone: false,
  selector: 'app-product-table',
  templateUrl: './product-table.component.html',
  styleUrls: ['./product-table.component.scss', './product-table.component.query.scss']
})
export class ProductTableComponent implements OnInit {

  @Input() data!: searchRenderInterface['other'][0];
  @Input() shippingInfo!: searchRenderInterface['shippingInfo'];
  @Input() fromPage!: string;
  @Input() columnsConfig?: Array<ColumnConfig> = [];
  sortOrder = 'asc';
  sortColumn = '';
  sortIcon = 'long-arrow-up';
  defaultColumnConfig: Array<ColumnConfig> = [];
  updateShippingInfoEvent!: Subscription;

  grouping = {
    autoExpandAll: true
  };

  public groupedData: searchRenderInterface['other'][0] = [];

  imgUrl: string = environment.imageUrl;
  adrHtml = '<img style="width: 17px;" src="'+this.imgUrl+'/ADR_Small.png" alt="" adr-class="adrIconNg">';

  constructor(
    private cartService: CartService,
    public renderer: Renderer2,
    private element: ElementRef,
    @Inject(DOCUMENT) private _document: Document,
    private sessionService: SessionService,
    private util: UtilitiesService,
    private dataTransmitter: DataTransmitterService
  ) { }

  session!: SessionDataInterface['data'];

  ngOnInit(): void {
    this.session = this.sessionService.getSession();
    this.updateShippingInfoEvent = this.cartService.updateShippingInfo.subscribe((data) => {
        this.setShippingInfo()
    });
    this.groupedData = this.data.slice(0, 20);
    this.defaultColumnConfig = this.util.merge(this.defaultColumnConfig, this.columnsConfig);
    let ndc = '';
    if (this.groupedData.length > 0 && this.groupedData[0].rx_otc !== 'Q') {
        for (let product of this.groupedData) {
            if (product.rx_otc !== 'Q' && product.ndc_clean !== '' && product.ndc_clean !== null) {
                ndc = product.ndc_clean;
                break ;
            }
        }
    }
    this.dataTransmitter.lane4AdData.next({ndc: ndc, pageName: this.fromPage});
  }

  ngOnChanges(changes: SimpleChanges): void {
    this.groupedData = this.data;
  }

  async loadMore() {
    const next = this.groupedData.length;
    if (this.data.length !== next) {
        this.groupedData = [...this.groupedData, ...this.data.slice(next, next + 30)];
    }      
  }

  config = {
    naMsg: 'N/A'
  };

  toolTip = {
    title: "<b class='toolTipTitle'>PACKAGE DESCRIPTION: </b>"
  };

  showColumnHeaders: boolean = true;

  checkBoxOptions = {
    text: "Expand All Groups",
    bindingOptions: {
        value: "grouping.autoExpandAll"
    }       
  };

  checkNotices(row: any) {
      return(row.is_refrigerated || row.is_hazardous);
  };

  checkDescription(packageDescription: string) {
      if (packageDescription !== null && packageDescription !== '' && packageDescription.trim().split(',')[0] !== 'bottle') {
          return true;
      } else {
          return false;
      }
  };

  /*
  * Return the given product is brand or generic
  * @param {string} flag
  * @returns {String}
  */
  genericOrBrand(flag: string, teCode: string, name: string){
    //checking flag variable should not be empty, null or undefined value.
    if(flag?.toLowerCase() === 'b'){
        return '| Brand';
    }
    else if(flag?.toLowerCase() === 'g'){
        var teRating = '';
        if(teCode !== '' && teCode !== null) {
            teRating = teCode+' ';
        }
        return '| '+teRating+ 'Generic';
    }
    return '';
  };

  @HostListener('window:scroll', ['$event'])
  onScroll(event: Event) {
    if (this.isScrollAtBottom()) {
      this.loadMore();
    }
  }

  /*
   * Adds updated cart data to shippingInfo data model
   */
  getShoppingCartSubscribe!:Subscription;
  setShippingInfo() {
       let suppliers = [];
       this.getShoppingCartSubscribe = this.cartService.getShoppingCart()
        .subscribe({
            next: (res: any) => {
                const dataArray = res.data;
                if (Object.keys(res.data).length > 0) {
                     const dataArray = Object.keys(res.data).map(key => ({key, value: res.data[key]}));
                     dataArray.forEach((supplier: any) => {
                        let supplierId = supplier.key;
                        if (typeof this.shippingInfo[supplierId] !== 'undefined') {
                            this.shippingInfo[supplierId]['cutoff_time'] = supplier.value.shippingData.cutoff_time;
                            this.shippingInfo[supplierId]['shipping_methods'] = supplier.value.shippingData.shipping_methods;
                            this.shippingInfo[supplierId]['supplier_total'] = supplier.value.totalOrderAmount;
                            suppliers.push(parseInt(supplierId));
                        }
                    });
                }
            },
            error: (err) => {
            this.cartService.errorCallBack(err);
          },
          complete: () => { },
        })
  };

  isScrollAtBottom(): boolean {
    const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
    const scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight || 0;
    const clientHeight = document.documentElement.clientHeight || window.innerHeight || 0;

    return ((scrollTop + clientHeight) + 150) >= scrollHeight;
  }

  /*
  * Hide Unit Price if admin hide price is checked.
  * @param {type} itemData
  * @returns {Boolean}
  */
  hidePrice(product: searchRenderInterface['other'][0][0]) {
    if(product.hide_pricing === 1 && !product.account_no) {
        return true;
    }
    return false;
  }

    /**
   * Sort dataset based on which header user has clicked and change sort icon on header.
   * @param event 
   * @param field 
   */
    customSort(event: any, field: string) {
      let element = this.element.nativeElement.querySelector('#'+field+' > div > div > i');
      this.renderer.removeClass(element, this.sortIcon);
      if (this.sortColumn !== '') {
        this.renderer.removeClass(this.element.nativeElement.querySelector('#'+this.sortColumn+' > div > div > i'), this.sortIcon);
      }
      // Toggles sort order basing the field is a previous or new one.
      if (this.sortColumn === field) {
        this.sortOrder = this.sortOrder === 'asc' ? 'desc' : 'asc';
      } else {
        this.sortOrder = 'asc';
      }
      sortArray(this.data, {
        by: field,
        order: this.sortOrder
      });
      this.sortIcon = this.sortOrder === 'asc' ? 'fa-long-arrow-up' : 'fa-long-arrow-down';
      this.sortColumn = field;
      this.groupedData = this.data.slice(0, 20);
      this.renderer.addClass(element, this.sortIcon);
    }
    
    /**
     * Check if rebate is shown.
     * @param itemData 
     * @returns boolean
     */
    showRebate(itemData: any) {
        return ((itemData.ipc_rebate_tier && itemData.ipc_rebate_tier != itemData.start_price) 
        || (itemData.buyer_sales_flag && this.session.trxade_gpo_member && itemData.rebate != itemData.start_price));
    }

    /**
     * Returns column name to be changed in the table header based on the column name passed.
     * @param column string
     * @returns string
     */
    getColumnName(column: string): string {
        let columnName = column;
        this.defaultColumnConfig.forEach((col: ColumnConfig) => {
            if (col.name === column) {
                columnName = col.alias;
            }
        });
        return columnName;
    }
    
    /**
     * Method to check if the Expiration Date is below 90 days or not
     * @param {string} expirationDate
     * @return {Boolean}
     */
    isExpireIn90Days(expirationDate: string) {
        return this.util.getExpireDateBelow90Days(expirationDate);
    }
    
    ngOnDestroy() {
        this.getShoppingCartSubscribe?.unsubscribe();
        this.updateShippingInfoEvent?.unsubscribe();
    }
}
