import { Component, OnInit, Input } from '@angular/core';
import {
  OrderItemDTO,
  LogisticianDTO,
  EnvironmentChannel,
  BranchDTO,
  OrderItemSubsetDTO,
  ProductDTO,
  VATDTO,
  VATType,
  PriceValueDTO,
  PriceDTO,
  VATValueDTO,
} from '@swagger/oms';
import { FormBuilder, FormGroup, Validators, AbstractControl } from '@angular/forms';
import { orderChannelMapper } from 'apps/sales/src/app/core/mappings/shelf.mapping';
import { Store, Select } from '@ngxs/store';
import { BranchSelectors } from 'apps/sales/src/app/core/store/selectors/branch.selector';
import { CollectingShelfService } from 'apps/sales/src/app/core/services/collecting-shelf.service';
import { VatState } from 'apps/sales/src/app/core/store/state/vat.state';
import { Observable, of } from 'rxjs';
import { take, map, catchError } from 'rxjs/operators';
import { SupplierState } from 'apps/sales/src/app/core/store/state/supplier.state';

@Component({
  selector: 'app-order-item-edit',
  templateUrl: './order-item-edit.component.html',
  styleUrls: ['./order-item-edit.component.scss'],
})
export class OrderItemEditComponent implements OnInit {
  @Input() orderItem: OrderItemDTO;
  @Input() logistician: LogisticianDTO;
  @Input() clientChannel: EnvironmentChannel;
  @Input() targetBranch: BranchDTO;
  @Input() multi = false;
  @Select(VatState.getVats) vats$: Observable<VATDTO[]>;
  shrinked = true;
  itemForm: FormGroup;
  sumbited = false;
  mwstValueList: {
    key: number;
    value: string;
    vatType: VATType;
    grossValue: number;
  }[];
  mwst: { key: number; value: string; vatType: VATType; grossValue: number };
  sscText: string;

  get itemControls() {
    return this.itemForm.controls;
  }

  get mwstControls() {
    return (this.itemForm.controls.mwst as FormGroup).controls;
  }

  constructor(private fb: FormBuilder, private store: Store, private shelfService: CollectingShelfService) {}

  ngOnInit() {
    this.initialize();
    this.initializeVatList();
  }

  initialize() {
    if (this.orderItem) {
      this.buildForm(this.fb, this.orderItem, this.logistician, this.clientChannel, this.targetBranch);
    }
  }

  initializeVatList() {
    this.vats$.pipe(take(1)).subscribe((vats: VATDTO[]) => {
      if (vats && vats.length > 0) {
        this.mwstValueList = vats.map((vat) => {
          if (vat) {
            return {
              key: vat.value,
              value: vat.name + '%',
              vatType: vat.vatType,
              grossValue: vat.value,
            };
          }
        });
      }
    });
  }

  buildForm(fb: FormBuilder, item: OrderItemDTO, logistician: LogisticianDTO, clientChannel: EnvironmentChannel, targetBranch: BranchDTO) {
    let price: number;
    if (item.grossPrice && item.grossPrice.value && item.grossPrice.value.value) {
      price = item.grossPrice.value.value;
    }
    let mwst: {
      key: number;
      value: string;
      vatType: VATType;
      grossValue: number;
    };
    if (item.grossPrice && item.grossPrice.vat) {
      mwst = {
        key: item.grossPrice.vat.inPercent,
        value: item.grossPrice.vat.inPercent + ' %',
        vatType: item.grossPrice.vat.vatType,
        grossValue: item.grossPrice.vat.value,
      };
    }

    let suplier: string;

    if (
      item &&
      item.subsetItems[0] &&
      item.subsetItems[0].data &&
      item.subsetItems[0].data.supplier &&
      item.subsetItems[0].data.supplier.id
    ) {
      const suppliers = this.store.selectSnapshot(SupplierState.getSuppliers);
      if (suppliers && suppliers[item.subsetItems[0].data.supplier.id]) {
        suplier = suppliers[item.subsetItems[0].data.supplier.id].name;
      }
    }

    let channel: string;
    if (clientChannel) {
      channel = orderChannelMapper[clientChannel];
    }
    let branch: string;
    if (targetBranch) {
      const branches = this.store.selectSnapshot(BranchSelectors.getBranches);
      if (branches && branches[targetBranch.id]) {
        branch = branches[targetBranch.id].name;
      }
    }
    let ssc: string;
    if (item.subsetItems && item.subsetItems[0] && item.subsetItems[0].data && item.subsetItems[0].data.ssc) {
      ssc = item.subsetItems[0].data.ssc;
    }
    let specialComment: string;
    if (item.subsetItems && item.subsetItems[0] && item.subsetItems[0].data && item.subsetItems[0].data.specialComment) {
      specialComment = item.subsetItems[0].data.specialComment;
    }
    this.itemForm = fb.group({
      quantity: [item.quantity + 'x', Validators.required],
      price: [price, Validators.required],
      isbn: [item.product.ean, Validators.required],
      suplier: [suplier, Validators.required],
      channel: [channel, Validators.required],
      targetBranch: [branch, Validators.required],
      mwst: fb.group({
        key: [mwst ? mwst.key : null],
        value: [mwst ? mwst.value : null],
        vatType: [mwst ? mwst.vatType : null],
        grossValue: [mwst ? mwst.grossValue : null],
      }),
      ssc: [ssc, Validators.required, this.validateSSc.bind(this)],
      specialComment: [specialComment],
    });
    this.itemForm.disable();
  }

  editInput(field: string, input: any) {
    const control = this.itemForm.get(field);
    control.enable();
    this.sumbited = false;
  }

  submitInput(field: string) {
    const control = this.itemForm.get(field);
    if (control.valid && control.dirty) {
      this.submit(field);
      control.disable();
    } else if (control.valid && !control.dirty) {
      control.disable();
    }
    this.sumbited = true;
  }

  editFormGroup(group: string, field: string, input: any) {
    const control = this.itemForm.get(group).get(field);
    control.enable();
    this.sumbited = false;
  }

  submitFormGroup(group: string, field: string) {
    const control = this.itemForm.get(group).get(field);
    if (control.valid && control.dirty) {
      this.submit(group, true);
      control.disable();
    } else if (control.valid && !control.dirty) {
      control.disable();
    }
    this.sumbited = true;
  }

  clear(field: string) {
    this.itemForm.get(field).patchValue(null);
  }

  clearMwst() {
    this.itemForm.get('mwst').patchValue({ key: null, value: null, vatType: null, grossValue: null });
  }

  mwstSelected(selection: { key: number; value: string; vatType: VATType; grossValue: number }) {
    this.mwst = selection;
    this.itemForm.get('mwst').get('key').patchValue(selection.key);
    this.itemForm.get('mwst').get('key').markAsDirty();
    this.itemForm.get('mwst').get('value').patchValue(selection.value);
    this.itemForm.get('mwst').get('value').markAsDirty();
    this.itemForm.get('mwst').get('vatType').patchValue(selection.vatType);
    this.itemForm.get('mwst').get('vatType').markAsDirty();
    this.itemForm.get('mwst').get('grossValue').patchValue(selection.grossValue);
    this.itemForm.get('mwst').get('grossValue').markAsDirty();
  }

  shrinkToggle() {
    this.shrinked = !this.shrinked;
  }

  async submit(field: string, isGroup: boolean = false) {
    if (!isGroup) {
      const control = this.itemForm.get(field);
      const param = <OrderItemDTO>{};
      const paramSubset = <OrderItemSubsetDTO>{};
      if (field === 'price') {
        param.grossPrice = <PriceDTO>{
          ...this.orderItem.grossPrice,
          value: <PriceValueDTO>{
            ...this.orderItem.grossPrice.value,
            value: control.value,
          },
        };
        this.submitItem(param);
      } else if (field === 'isbn') {
        param.product = <ProductDTO>{
          ...this.orderItem.product,
          ean: control.value,
        };
        this.submitItem(param);
      } else if (field === 'ssc' && this.sscText) {
        paramSubset.ssc = control.value;
        paramSubset.sscText = this.sscText;
        this.submitItemSubset(paramSubset);
      } else if (field === 'specialComment') {
        paramSubset.specialComment = control.value;
        this.submitItemSubset(paramSubset);
      }
    } else {
      if (field === 'mwst') {
        const keyControl = this.itemForm.get(field).get('key');
        const percentage = keyControl.value as number;
        const vatTypeControl = this.itemForm.get(field).get('vatType');
        const vatType = vatTypeControl.value as VATType;
        const priceControl = this.itemForm.get('price');
        const priceValue = priceControl.value as number;
        const value = Math.round(priceValue * percentage) / 100;
        const param = <OrderItemDTO>{};
        param.grossPrice = <PriceDTO>{
          ...this.orderItem.grossPrice,
          vat: <VATValueDTO>{
            ...this.orderItem.grossPrice.vat,
            inPercent: percentage,
            value: value,
            vatType: vatType,
          },
        };
        this.submitItem(param);
      }
    }
  }

  submitItem(orderItem: OrderItemDTO) {
    if (this.orderItem) {
      const orderId = this.orderItem.order.id;
      this.shelfService
        .patchOrderItem(orderId, this.orderItem.id, orderItem)
        .toPromise()
        .then((response) => {
          if (response) {
            this.orderItem = response;
          }
          this.initialize();
        })
        .catch((error) => {
          console.error(error);
          this.initialize();
        });
    }
  }

  submitItemSubset(orderItemsubset: OrderItemSubsetDTO) {
    if (this.orderItem.subsetItems && [0] && this.orderItem.subsetItems[0].data && this.orderItem.subsetItems[0].data.id) {
      const orderId = this.orderItem.order.id;
      const orderItemSubsetId = this.orderItem.subsetItems[0].id;
      this.shelfService
        .patchOrderItemSubset(orderId, this.orderItem.id, orderItemSubsetId, orderItemsubset)
        .toPromise()
        .then((response) => {
          if (response) {
            this.orderItem = {
              ...this.orderItem,
              subsetItems: this.orderItem.subsetItems.map(() => {
                return { data: response, id: orderItemSubsetId };
              }),
            };
          }
          this.initialize();
        })
        .catch((error) => {
          console.error(error);
          this.initialize();
        });
    }
  }

  private validateSSc$(status: string, supplierId: number) {
    return this.shelfService.getMessageText(status, supplierId).pipe(
      catchError((error) => {
        console.error(error);
        return of(undefined);
      }),
      map((result) => {
        this.sscText = result;
        if (!result) {
          return { sscNotValid: true };
        }
      })
    );
  }

  validateSSc(control: AbstractControl) {
    return control.value && this.orderItem.subsetItems[0].data.supplier
      ? this.validateSSc$(control.value, this.orderItem.subsetItems[0].data.supplier.id)
      : of(null);
  }
}
