import { Component, OnInit } from '@angular/core';
import { Location } from '@angular/common';
import { FormBuilder, FormGroup } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { CrmCustomerService } from '@domain/crm';
import { CountryDTO, CustomerDTO, KeyValueDTOOfStringAndString } from '@swagger/crm';
import { Observable } from 'rxjs';
import { map, switchMap, first } from 'rxjs/operators';
import { AddressSelectionModalService } from '../../../modals/address-selection-modal/address-selection-modal.service';
import { BreadcrumbService } from '@core/breadcrumb';
import { ApplicationService } from '@core/application';
import { HttpErrorResponse } from '@angular/common/http';
import { camelCase } from 'lodash';

@Component({ template: '' })
export abstract class ShippingCreateComponent implements OnInit {
  control: FormGroup;
  countries$: Observable<CountryDTO[]>;
  customer$: Observable<CustomerDTO>;
  customerFeatures$: Observable<KeyValueDTOOfStringAndString[]>;
  customerType$: Observable<string>;
  isWebshopOrGuest$: Observable<boolean>;
  customerFeatureB2bOrB2c$: Observable<string>;

  get customerId(): number {
    return Number(this.activatedRoute.snapshot.params['customerId']);
  }

  constructor(
    public customerService: CrmCustomerService,
    public fb: FormBuilder,
    private activatedRoute: ActivatedRoute,
    private location: Location,
    private addressSelectionModal: AddressSelectionModalService,
    private breadcrumb: BreadcrumbService,
    private application: ApplicationService
  ) {}

  ngOnInit() {
    this.customer$ = this.customerService.getCustomer(this.customerId, 2).pipe(map((response) => response.result));
    this.customerFeatures$ = this.customer$.pipe(map((customer: CustomerDTO) => Object.values(customer.features).filter((f) => f.enabled)));
    this.customerType$ = this.customerFeatures$.pipe(
      map(
        (features: KeyValueDTOOfStringAndString[]) =>
          features.find((f) => f.key === 'store' || f.key === 'webshop' || f.key === 'b2b' || f.key === 'guest')?.key
      )
    );
    this.isWebshopOrGuest$ = this.customerType$.pipe(map((type) => type === 'webshop' || type === 'guest'));
    this.customerFeatureB2bOrB2c$ = this.customerType$.pipe(map((type) => (type === 'b2b' ? 'b2b' : 'b2c')));
    this.countries$ = this.isWebshopOrGuest$.pipe(
      switchMap((webshopOrGuest) => {
        if (!webshopOrGuest) {
          return this.customerService.getCountries().pipe(map((p) => p.result));
        } else {
          return this.customerService.getCountries().pipe(
            map((p) => p.result),
            map((countries) => countries.filter((country) => country.name === 'Deutschland'))
          );
        }
      })
    );
    this.control = this.initForm();
    this.createBreadcrumb();
  }

  abstract initForm(): FormGroup;

  async createBreadcrumb() {
    const customerFeature: string = await this.customerFeatureB2bOrB2c$.pipe(first()).toPromise();
    await this.breadcrumb.addBreadcrumbIfNotExists({
      key: this.application.activatedProcessId,
      name: 'Lieferadresse hinzufügen',
      path: `/kunde/${this.application.activatedProcessId}/customer/${this.customerId}/shipping/create/${customerFeature}`,
      tags: ['customer', 'shipping', 'create'],
      section: 'customer',
      params: {},
    });
  }

  async submit() {
    if (this.control.invalid || this.control.disabled) {
      return;
    }
    this.control.disable();

    try {
      let address = await this.addressSelectionModal.validateAddress(this.control.value.address);
      if (address) {
        this.control.patchValue({ address });
      }
    } catch (error) {
      this.control.enable();
      if (error instanceof HttpErrorResponse) {
        if (error.error.invalidProperties) {
          const invProps = error.error.invalidProperties;
          const keys = Object.keys(invProps);
          for (const key of keys) {
            this.control.get('address')?.get(camelCase(key))?.setErrors({ validateAddress: invProps[key] });
          }
        }
      }
      return;
    }

    try {
      await this.customerService.createShippingAddress(this.customerId, this.control.value, this.control.value.isDefault).toPromise();
      this.location.back();
    } catch (err) {
      this.control.enable();
    }
  }
}
