import { Component, ChangeDetectionStrategy, OnInit, OnDestroy, ChangeDetectorRef, ElementRef, ViewChild } from '@angular/core';
import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { ApplicationService } from '@core/application';
import { BreadcrumbService } from '@core/breadcrumb';
import { CrmCustomerService } from '@domain/crm';
import { AddressDTO, CustomerDTO } from '@swagger/crm';
import { UiErrorModalComponent, UiModalService } from '@ui/modal';
import { AddressSelectionModalService } from '../modals/address-selection-modal/address-selection-modal.service';
import { CustomerCreateComponentBase } from './customer-create.component';
import { validateEmail } from '../validators/email-validator';
import { Subscription } from 'rxjs';
import { DomainCheckoutService } from '@domain/checkout';
import { UiValidators } from '@ui/validators';
import { isStringEmpty } from '@utils/common';
import { HttpErrorResponse } from '@angular/common/http';
import { map } from 'rxjs/operators';

@Component({
  selector: 'page-customer-create-branch',
  templateUrl: 'customer-create-branch.component.html',
  styleUrls: ['customer-create.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CustomerCreateBranchComponent extends CustomerCreateComponentBase implements OnInit, OnDestroy {
  @ViewChild('formControl')
  formControlRef: ElementRef;

  shippingAddressSubscription: Subscription;
  organisationSubscription: Subscription;
  addressSubscription: Subscription;

  get addressGroup(): AbstractControl {
    return this.control?.get('address');
  }

  get shippingAddressGroup(): AbstractControl {
    return this.control?.get('shippingAddress');
  }

  constructor(
    public activatedRoute: ActivatedRoute,
    public router: Router,
    private fb: FormBuilder,
    public modal: UiModalService,
    public customerService: CrmCustomerService,
    public breadcrumb: BreadcrumbService,
    public application: ApplicationService,
    public addressSelectionModal: AddressSelectionModalService,
    public checkoutService: DomainCheckoutService,
    public cdr: ChangeDetectorRef,
    private _modal: UiModalService
  ) {
    super();
  }

  ngOnInit() {
    this.init();

    if (!!this.p4mUser) {
      this.cusotmers$ = this.cusotmers$.pipe(
        map((data) => ({
          values: data.values.filter((f) => f.value === 'store'),
        }))
      );
    }

    this.shippingAddressGroup.disable();
    this.shippingAddressSubscription = this.control.get('differentShippingAddress').valueChanges.subscribe((isChecked) => {
      if (isChecked) {
        this.shippingAddressGroup.enable();
        this.setShippingAddressValidators(this.shippingAddressGroup);
      } else {
        this.shippingAddressGroup.disable();
        this.clearShippingAddressValidators(this.shippingAddressGroup);
        this.control.updateValueAndValidity();
      }
    });

    this.organisationSubscription = this.organisationGroup.get('name').valueChanges.subscribe((value: string) => {
      if (!value) {
        this.organisationGroup.get('department').reset('', { onlySelf: true });
        this.organisationGroup.get('vatId').reset('', { onlySelf: true });
      }
    });

    this.addressSubscription = this.addressGroup.valueChanges.subscribe((value: AddressDTO) => {
      if (value) {
        const country = this.addressGroup.get('country');
        if (!country.value) {
          country.setValue('DEU');
        } else if (this.isAddressEmpty(value)) {
          country.setValue('', { onlySelf: true });
        }
      }
    });
  }

  isAddressEmpty(value: AddressDTO): boolean {
    return (
      isStringEmpty(value?.street) && isStringEmpty(value?.streetNumber) && isStringEmpty(value?.zipCode) && isStringEmpty(value?.city)
    );
  }

  ngOnDestroy(): void {
    if (this.shippingAddressSubscription) {
      this.shippingAddressSubscription.unsubscribe();
    }

    if (this.organisationSubscription) {
      this.organisationSubscription.unsubscribe();
    }

    if (this.addressSubscription) {
      this.addressSubscription.unsubscribe();
    }
  }

  createControl(customer?: CustomerDTO): FormGroup {
    const fb = this.fb;

    return fb.group({
      organisation: fb.group({
        name: fb.control(customer?.organisation?.name),
        department: fb.control(customer?.organisation?.department),
        vatId: fb.control(customer?.organisation?.vatId),
      }),
      gender: fb.control(customer?.gender, [Validators.required, Validators.min(1)]),
      title: fb.control(customer?.title),
      lastName: fb.control(customer?.lastName, [Validators.required]),
      firstName: fb.control(customer?.firstName, [Validators.required]),
      dateOfBirth: fb.control(customer?.dateOfBirth, [UiValidators.date]),
      communicationDetails: fb.group({
        email: fb.control(customer?.communicationDetails?.email, [validateEmail]),
        phone: fb.control(customer?.communicationDetails?.phone, [UiValidators.phone]),
        mobile: fb.control(customer?.communicationDetails?.mobile, [UiValidators.phone]),
      }),
      address: fb.group({
        street: fb.control(customer?.address?.street),
        streetNumber: fb.control(customer?.address?.streetNumber),
        zipCode: fb.control(customer?.address?.zipCode),
        city: fb.control(customer?.address?.city),
        country: fb.control(!this.isAddressEmpty(customer?.address) ? customer?.address?.country : ''),
        info: fb.control(customer?.address?.info),
      }),
      differentShippingAddress: fb.control(false),
      shippingAddress: fb.group({
        organisation: fb.group({
          name: fb.control(''),
          department: fb.control(''),
          vatId: fb.control(''),
        }),
        gender: fb.control(undefined),
        title: fb.control(''),
        firstName: fb.control(''),
        lastName: fb.control(''),
        address: fb.group({
          street: fb.control(''),
          streetNumber: fb.control(''),
          zipCode: fb.control(''),
          city: fb.control(''),
          info: fb.control(''),
          country: fb.control('DEU'),
        }),
      }),
    });
  }

  async submit(): Promise<void> {
    if (this.control.disabled) {
      return;
    }

    if (this.control.invalid) {
      this.control.disable({ emitEvent: false });
      setTimeout(() => {
        this.enableControl();
        this.focusFirstInvalidFormControl(this.formControlRef);
      }, 200);
      return;
    }

    this.control.disable({ emitEvent: false });

    try {
      let address = await this.addressSelectionModal.validateAddress(this.control.value.address);
      if (address) {
        if (typeof address === 'string') {
          if (address === 'close') {
            this.enableControl();
            return;
          }
        } else {
          this.control.patchValue({ address });
        }
      }
    } catch (error) {
      this.enableControl();
      if (error instanceof HttpErrorResponse) {
        if (error.error.invalidProperties) {
          this.setValidateAddressError(error.error?.invalidProperties, this.control.get('address'));
        }
      }
      return;
    }

    try {
      if (this.control.value.differentShippingAddress) {
        const shippingAddress = await this.addressSelectionModal.validateAddress(this.control.value.shippingAddress.address);
        if (shippingAddress) {
          if (typeof shippingAddress === 'string') {
            if (shippingAddress === 'close') {
              this.enableControl();
              return;
            }
          } else {
            this.control.patchValue({ shippingAddress });
          }
        }
      }
    } catch (error) {
      this.enableControl();
      if (error instanceof HttpErrorResponse) {
        if (error.error.invalidProperties) {
          this.setValidateAddressError(error.error?.invalidProperties, this.control.get('shippingAddress').get('address'));
        }
      }
      return;
    }

    try {
      let newCustomer: CustomerDTO = this.control.value;

      if (!!this.p4mUser) {
        newCustomer.features = newCustomer.features ? [...newCustomer.features, this.p4mUser] : [this.p4mUser];
      }
      const response = await this.customerService.createBranchCustomer(newCustomer).toPromise();

      if (this.control.value.differentShippingAddress) {
        try {
          const shippingResponse = await this.customerService
            .createShippingAddress(response.result.id, this.control.value.shippingAddress, true)
            .toPromise();
          if (shippingResponse.error) {
            throw new Error(shippingResponse.message);
          }
        } catch (error) {
          console.error(error);
        }
      }

      if (response.error) {
        this.enableControl();
        throw new Error(response.message);
      } else {
        this.removeBreadcrumb();
        this.router.navigate(['/kunde', this.application.activatedProcessId, 'customer', response.result.id]);
      }
    } catch (error) {
      this.setValidationError(error.error?.invalidProperties, this.control);
      this._modal.open({ content: UiErrorModalComponent, data: error, title: 'Fehler beim Anlegen eines Filialkunden' });
    }
  }

  enableControl() {
    this.control.enable();

    if (!this.control.get('differentShippingAddress').value) {
      this.control.get('differentShippingAddress').disable();
    }

    this.control.markAllAsTouched();
    this.control.updateValueAndValidity();
  }
}
