import {
  Component,
  ElementRef,
  OnDestroy,
  OnInit,
  Renderer2,
  ViewChild,
} from '@angular/core';
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
import { Store } from '@ngrx/store';
import {
  WindowCloseResult,
  WindowRef,
  WindowService,
} from '@progress/kendo-angular-dialog';
import { CellClickEvent, GridComponent } from '@progress/kendo-angular-grid';
import { TextBoxComponent } from '@progress/kendo-angular-inputs';
import { HierarchyBindingDirective } from '@progress/kendo-angular-menu';
import { FilterExpandSettings } from '@progress/kendo-angular-treeview';
import { TreeViewSize } from '@progress/kendo-angular-treeview/dist/es2015/size';
import { paperclipIcon } from '@progress/kendo-svg-icons';
import { Observable, of, Subscription } from 'rxjs';
import {
  debounceTime,
  distinctUntilChanged,
  filter,
  map,
  switchMap,
  tap,
} from 'rxjs/operators';
import { AuthService } from 'src/app/auth/services/auth.service';
import { BrandFilter } from 'src/app/models/brand.model';
import { Departamento } from 'src/app/models/departamento.model';
import { FilterProduct } from 'src/app/models/filter-product.model';
import { SaleProduct, Stock } from 'src/app/models/sale-product.model';
import { LookupService } from 'src/app/services/lookup.service';
import { ProductService } from 'src/app/services/product.service';
import { ShoppingService } from 'src/app/services/shopping.service';
import {
  AddItemAction,
  LoadShoppingItemsAction,
  UpdateQuantityItemAction,
} from '../../store/actions/shopping.action';
import { SaleState } from '../../store/models/sale-state.model';
import { ShoppingItem } from '../../store/models/shopping-item';
import { PreCustomerComponent } from '../pre-customer/pre-customer.component';

const hasClass = (el, className) => new RegExp(className).test(el.className);

const isChildOf = (el, className) => {
  while (el && el.parentElement) {
    if (hasClass(el.parentElement, className)) {
      return true;
    }
    el = el.parentElement;
  }
  return false;
};

@Component({
  selector: 'app-sales-appbar',
  templateUrl: './sales-appbar.component.html',
  styleUrls: ['./sales-appbar.component.scss'],
})
export class SalesAppbarComponent implements OnInit, OnDestroy {
  @ViewChild('hierarchy')
  public hierarchy: HierarchyBindingDirective;
  public selectedComponentSize: TreeViewSize = 'medium';
  public selectedKeys: any[] = [];
  public expandedKeys: any[] = [];
  @ViewChild('productCard') productCard: ElementRef;
  @ViewChild('quantityCart') quantityCart: TextBoxComponent;

  /* controle grid do carrinho de compras */
  @ViewChild(GridComponent) private grid: GridComponent;
  private editedRowIndex: number;
  private isNew = false;
  public get isInEditingMode(): boolean {
    return this.editedRowIndex !== undefined || this.isNew;
  }
  /* fim controle do carrinho de compras */

  existsProduct = true;
  searchProduct = new FormControl();
  quantitySale = new FormControl('1');
  public icons = { paperclip: paperclipIcon };
  pageNumber = 1;
  pageSize = 100;
  public themeColor = 'inherit';
  public keys: string[] = [];

  public windowTop = 100;
  public windowLeft = 0;
  public opened = false;

  /* Image card product */
  public imageWidth = '100%';
  public imageHeight = '350px';

  products$: Observable<SaleProduct[]>;
  promotions$: Observable<SaleProduct[]>;
  shopping$: Observable<ShoppingItem[]>;
  shoppingItens: ShoppingItem[] = [];
  totalCart$: Observable<number>;

  searchSubscription: Subscription;
  loadProducts: SaleProduct[];
  departmentSubscription: Subscription;
  departments$: Observable<Departamento[]>;
  stock$: Observable<Stock[]>;
  images: string[] = [];
  brands: BrandFilter[] = [];
  items: any[];
  categories: any[] = [];

  loading$: Observable<boolean>;
  error$: Observable<Error>;
  newShoppingItem: ShoppingItem = {
    id: null,
    invoiceStore: null,
    idCart: null,
    idProduct: null,
    description: null,
    ean: null,
    promotion: null,
    image: null,
    productType: null,
    quantity: null,
    price: null,
    smallDescription: null,
    deliveryType: null,
    stockStore: null,
    seller: null,
    listPrice: null,
    brand: null,
    percentUpQuantity: null,
    upQuantity: null,
    discount: null,
    discountValue: null,
    userDiscount: null,
    mutiple: null,
    auxDescription: null,
    base: null,
    letter: null,
    line: null,
    can: null,
    color: null,
  };

  constructor(
    private productService: ProductService,
    private store: Store<SaleState>,
    private readonly authService: AuthService,
    private readonly shoppingService: ShoppingService,
    private readonly lookupService: LookupService,
    private readonly fb: FormBuilder,
    private windowService: WindowService,
    private renderer: Renderer2
  ) {}

  public expandedOnClear = 'none';

  public data: any[] = [];

  public formQuantity: FormGroup = this.fb.group({
    quantity: [],
  });
  public formFilter: FormGroup = this.fb.group({
    onlyWithStock: new FormControl(false),
    outLine: new FormControl(false),
    campaign: new FormControl(false),
  });
  public checkedKeysBrand: any[] = [];
  public selectedBrandKeys: any[] = [];
  public childrenBrand = (dataItem: any): Observable<any[]> =>
    of(dataItem.items);
  public hasChildrenBrand = (dataItem: any): boolean => !!dataItem.items;

  ngOnDestroy(): void {
    this.departmentSubscription.unsubscribe();
    this.searchSubscription.unsubscribe();
  }

  ngOnInit(): void {
    this.searchSubscription = this.searchProduct.valueChanges
      .pipe(
        map((value) => value.trim()),
        filter((value) => value.length > 3),
        debounceTime(400),
        distinctUntilChanged(),
        tap((value) => (this.loadProducts = null)),
        switchMap((value) =>
          this.productService.searchProduct(
            this.authService.getStore(),
            1,
            50,
            value
          )
        ),
        tap((products) => console.log(products)),
        map((products) => (this.loadProducts = products))
      )
      .subscribe();

    this.shopping$ = this.store.select((store) => store.shopping.list);
    this.totalCart$ = this.store.select((store) => store.shopping.total);
    this.loading$ = this.store.select((store) => store.shopping.loading);
    this.error$ = this.store.select((store) => store.shopping.error);

    this.shopping$.subscribe((data) => {
      this.shoppingItens = JSON.parse(JSON.stringify(data));
    });
    this.totalCart$.subscribe((data) => console.log(data));
    const idCart = this.shoppingService.getCart();
    this.store.dispatch(new LoadShoppingItemsAction(idCart));

    this.getSaleProducts();
    // this.getSalePromotions();

    this.departments$ = this.lookupService.getDepartments();

    this.departments$ // departmentSubscription = this.lookupService.getDepartments()
      .subscribe((departments) => {
        console.log(departments);
        this.items = this.mapItems(
          departments.filter((d) => d.tituloEcommerce != null),
          ['tituloEcommerce', 'descricaoSecao'],
          ['secoes']
        );
        this.data = this.items;
      });
  }

  selectedCategory(data: any) {
    console.log(data.dataItem.path);
    this.getProductByDepartment(data.dataItem.path);
  }

  keyDownFunction(event) {
    if (event.keyCode === 13) {
      // tslint:disable-next-line: no-shadowed-variable
      const filter: FilterProduct = {
        brands: [],
        text: this.searchProduct.value,
      };
      this.searchProducts(this.searchProduct.value);
    }
  }

  selectDepartment(select: any) {
    console.log(select.item.path);
    this.getProductByDepartment(select.item.path);
  }

  // convert the received data to menu items.
  private mapItems(
    items: any[],
    textFields: string[],
    childFields: string[],
    level: number = 0
  ): any[] {
    const childField = childFields[level];
    const textField = textFields[level];

    return items.map((item) => {
      const result: any = {
        text: item[textField],
        path: item.url,
      };
      // convert the children data to menu items.
      if (childField && item[childField]) {
        result.items = this.mapItems(
          item[childField],
          textFields,
          childFields,
          level + 1
        );
      }
      console.log(result);
      return result;
    });
  }

  public isExpanded = (dataItem: any, index: string) => {
    return this.keys.indexOf(index) > -1;
  };

  public handleCollapse(node) {
    this.keys = this.keys.filter((k) => k !== node.index);
  }

  public handleExpand(node) {
    this.keys = this.keys.concat(node.index);
  }

  public filterExpandSettings: FilterExpandSettings = {
    maxAutoExpandResults: 4,
  };

  public children = (dataitem: any): Observable<any[]> => of(dataitem.items);
  public hasChildren = (dataitem: any): boolean => !!dataitem.items;

  public openClose(isOpened: boolean) {
    this.opened = isOpened;
  }

  getSaleProducts(filterProduct: FilterProduct = null) {
    try {
      console.log(filterProduct);
      this.categories = [];
      this.products$ = this.productService.getSaleProducts(
        this.authService.getStore(),
        this.pageNumber,
        this.pageSize,
        filterProduct
      );
      this.products$.subscribe((products) => {
        products.forEach((product) => {
          const brandFilter = this.brands.find(
            (brand) => brand.description === product.brand
          );
          if (brandFilter == null) {
            const newBrand = new BrandFilter();
            newBrand.description = product.brand;
            newBrand.checked = false;
            this.brands.push(newBrand);
          }
          if (
            !this.categories.find(
              (category) => category.description === product.category
            )
          ) {
            this.categories.push({ description: product.category });
          }
        });
      });
    } catch (e) {
      console.log('Erro ao consultar produtos.');
      console.log(e);
    }
  }

  searchProducts(text: string) {
    try {
      this.categories = [];
      this.products$ = this.productService.searchProduct(
        this.authService.getStore(),
        this.pageNumber,
        this.pageSize,
        text
      );
      this.products$.subscribe((products) => {
        products.forEach((product) => {
          const brandFilter = this.brands.find(
            (brand) => brand.description === product.brand
          );
          if (brandFilter == null) {
            const newBrand = new BrandFilter();
            newBrand.description = product.brand;
            newBrand.checked = false;
            this.brands.push(newBrand);
          }
          if (
            !this.categories.find(
              (category) => category.description === product.category
            )
          ) {
            this.categories.push({ description: product.category });
          }
        });
      });
    } catch (e) {
      console.log('Erro ao consultar produtos.');
      console.log(e);
    }
  }

  getProductByDepartment(urlDepartment: string) {
    let url = '';
    console.log(urlDepartment);
    if (urlDepartment.includes('/')) {
      url = 'section/' + urlDepartment;
    } else {
      url = 'department/' + urlDepartment;
    }
    try {
      this.brands = [];
      this.categories = [];
      this.products$ = this.productService.getProductByDepartment(
        this.authService.getStore(),
        this.pageNumber,
        this.pageSize,
        url
      );
      this.products$.subscribe((products) => {
        products.forEach((product) => {
          const brandFilter = this.brands.find(
            (brand) => brand.description === product.brand
          );
          if (brandFilter == null) {
            const newBrand = new BrandFilter();
            newBrand.description = product.brand;
            newBrand.checked = false;
            this.brands.push(newBrand);
          }
          if (
            !this.categories.find(
              (category) => category.description === product.category
            )
          ) {
            this.categories.push({ description: product.category });
          }
        });
      });
    } catch (e) {
      console.log('Erro ao consultar produtos.');
      console.log(e);
    }
  }

  getSalePromotions(filterProduct: FilterProduct = null) {
    try {
      this.promotions$ = this.productService.getSalePromotions(
        this.authService.getStore(),
        this.pageNumber,
        this.pageSize,
        filterProduct
      );
      this.promotions$.subscribe((promotions) => {
        promotions.forEach((promotion) => {
          const brandFilter = this.brands.find(
            (brand) => brand.description === promotion.brand
          );
          if (brandFilter == null) {
            const newBrand = new BrandFilter();
            newBrand.description = promotion.brand;
            newBrand.checked = false;
            this.brands.push(newBrand);
          }
        });
      });
    } catch (e) {
      console.log('Erro ao consultar promoções.');
      console.log(e);
    }
  }

  /* createItemShopping(value: SaleProduct) {
     const idCart = this.shoppingService.getCart();
     this.store.dispatch(new AddItemAction({
       id: null, idCart, // '906488c9-249f-4253-b5e7-25033d597229',
       idProduct: value.idProduct, description: value.title, image: this.getImage(value.urlImage), productType: value.productType,
       quantity: 1, price: value.salePrice, deliveryType: null, stockStore: null, seller: null
     }));
   }*/

  getImage(urlImage: string) {
    if (urlImage === null) {
      return '';
    }
    if (urlImage.length > 0) {
      const re = /\s*;\s*/;
      if (urlImage.indexOf(';') === -1) {
        urlImage += ';';
      }
      this.images = urlImage.split(re);
      return this.images[0];
    }
  }

  addItem(value: SaleProduct) {
    try {
      console.log(value);
      const idCart = this.shoppingService.getCart();
      this.store.dispatch(
        new AddItemAction({
          id: null,
          idCart,
          invoiceStore: this.authService.getStore(),
          idProduct: value.idProduct,
          description: value.title,
          image: this.getImage(value.urlImage),
          productType: value.productType,
          quantity: 1,
          price: value.salePrice,
          deliveryType: null,
          stockStore: null,
          seller: null,
          discount: null,
          discountValue: null,
          listPrice: value.listPrice,
          userDiscount: null,
          mutiple: value.mutiple,
          auxDescription: null,
          brand: value.brand,
          smallDescription: value.smallDescription,
          ean: value.ean,
          promotion: value.promotion,
          percentUpQuantity: 0,
          upQuantity: 0,
          base: value.base,
          letter: value.letter,
          line: value.line,
          color: value.color,
          can: value.can,
        })
      );
    } catch (e) {
      console.log(e);
    }
  }

  updateItem(value: ShoppingItem, quantity: number) {
    try {
      console.log(value);
      const idCart = this.shoppingService.getCart();
      this.store.dispatch(
        new UpdateQuantityItemAction({
          id: value.id,
          idCart,
          invoiceStore: this.authService.getStore(),
          idProduct: value.idProduct,
          description: value.description,
          image: value.image,
          productType: value.productType,
          quantity,
          price: value.price,
          deliveryType: value.deliveryType,
          stockStore: value.stockStore,
          percentUpQuantity: value.percentUpQuantity,
          upQuantity: value.upQuantity,
          seller: value.seller,
          discount: value.discount,
          discountValue: value.discountValue,
          promotion: value.promotion,
          listPrice: value.listPrice,
          userDiscount: value.userDiscount,
          mutiple: value.mutiple,
          auxDescription: null,
          smallDescription: value.smallDescription,
          brand: value.brand,
          ean: value.ean,
          base: value.base,
          letter: value.letter,
          line: value.line,
          color: value.color,
          can: value.can,
        })
      );
    } catch (e) {
      console.log(e);
    }
  }

  selectBrand(brand: any) {
    this.brands
      .filter((data) => data.description === brand.description)
      .forEach((item) => {
        item.checked = !item.checked;
      });
    const brandsSelect = this.brands
      .filter((data) => data.checked)
      .map((item) => item.description);
    const filterProduct: FilterProduct = { brands: brandsSelect };
    console.log(filterProduct);
    this.getSaleProducts(filterProduct);
    // this.getSaleProducts();
  }

  getUserName() {
    return this.authService.getUserName();
  }

  getSeller() {
    return this.authService.getSeller();
  }

  public openFormPreCustomer() {
    console.log(this.productCard);
    const windowRef: WindowRef = this.windowService.open({
      title: 'Pré-cadastro de cliente',
      content: PreCustomerComponent,
      width: 350,
      height: 400,
    });

    windowRef.result.subscribe((result) => {
      if (result instanceof WindowCloseResult) {
        console.log('WindowCloseResult', result);
      }
    });

    windowRef.content.instance.submitForm.subscribe((formData) => {
      // handle form data
      console.log(formData);
      localStorage.setItem('preCustomer', JSON.stringify(formData));
      windowRef.close();
    });
  }

  receiveProductCard(product: any) {
    try {
      const baseValue = (product?.base ?? '').toString().trim().toUpperCase();
      if (baseValue === 'S') {
        return;
      }
      const idCart = this.shoppingService.getCart();
      const quantitySale =
        Math.ceil(product.quantity / product.mutiple) * product.mutiple;
      this.store.dispatch(
        new AddItemAction({
          id: null,
          idCart,
          invoiceStore: this.authService.getStore(),
          idProduct: product.idProduct,
          description: product.title,
          image: this.getImage(product.urlImage),
          productType: product.productType,
          quantity: quantitySale,
          price: product.salePrice,
          deliveryType: product.productType === 'A' ? 'RI' : 'EN',
          stockStore:
            product.productType === 'A' ? this.authService.getStore() : '6',
          seller: this.authService.getSeller(),
          discount: 0,
          discountValue: 0,
          ean: product.ean,
          promotion: product.promotion,
          percentUpQuantity: 0,
          upQuantity: 0,
          listPrice: product.listPrice,
          userDiscount: null,
          mutiple: product.mutiple,
          auxDescription: null,
          smallDescription: product.description,
          brand: product.brand,
          base: product.base,
          letter: product.letter,
          line: product.line,
          color: product.color,
          can: product.can,
        })
      );
    } catch (e) {
      console.log(e);
    }
  }

  /* Funções para alterar quantidade dos itens existentes no carrinho */
  addQuantity(product: ShoppingItem) {
    const oldValue = product.quantity;
    let addQuantity = 1;
    if (product.mutiple !== 1) {
      addQuantity = product.mutiple;
    }
    const newValue = oldValue + addQuantity;
    console.log(product);
    this.stock$ = this.productService.getStocks(
      this.authService.getStore(),
      product.idProduct
    );
    this.stock$.subscribe((stocks) => {
      console.log(product);
      const stock = stocks.filter((s) => s.store === product.stockStore);
      console.log(stock);
      if (stock[0].quantity >= newValue) {
        this.quantityCart.value = newValue.toString();
        this.updateItem(product, newValue);
      }
    });
  }

  addQuantity2(dataItem) {
    const oldValue = dataItem.quantity;
    let addQuantity = 1;
    if (dataItem.mutiple !== 1) {
      addQuantity = dataItem.mutiple;
    }
    const newValue = oldValue + addQuantity;
    let updateItem: ShoppingItem;
    updateItem = JSON.parse(JSON.stringify(dataItem));
    updateItem.quantity = newValue;

    this.stock$ = this.productService.getStocks(
      this.authService.getStore(),
      updateItem.idProduct
    );
    this.stock$.subscribe((stocks) => {
      const stock = stocks.filter((s) => s.store === updateItem.stockStore);
      if (stock[0].quantity >= newValue) {
        this.updateItem(updateItem, newValue);
      }
    });
  }

  minusQuantity(dataItem) {
    const oldValue = dataItem.quantity; // this.formQuantity.get('quantity').value;
    let addQuantity = 1;
    if (dataItem.mutiple !== 1) {
      addQuantity = dataItem.mutiple;
    }
    let newValue = oldValue - addQuantity;
    if (newValue < 0 || newValue < dataItem.mutiple) {
      newValue = dataItem.mutiple;
    }
    let updateItem: ShoppingItem;
    updateItem = JSON.parse(JSON.stringify(dataItem));
    updateItem.quantity = newValue;
    this.updateItem(updateItem, newValue);
  }

  public editHandler({
    sender,
    columnIndex,
    rowIndex,
    dataItem,
  }: CellClickEvent): void {
    this.editedRowIndex = rowIndex;
    console.log(dataItem);
  }

  public selectedBrand() {
    console.log(this.selectedBrandKeys.join(','));
    const selectBrands: string[] = [];
    this.selectedBrandKeys.forEach((key) => {
      const brand = this.brands[key];
      selectBrands.push(brand.description);
    });
    const filterProduct: FilterProduct = { brands: selectBrands };
    console.log(filterProduct);
    this.getSaleProducts(filterProduct);
  }

  public selectCategory(category: any) {
    console.log(category);
  }
}
