import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject, Observable, of } from 'rxjs';
import { User, Features } from '../../../../core/models/user.model';
import { Select, Store } from '@ngxs/store';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import {
  ChangeCurrentRoute,
  SetActiveCustomer,
  UpdateProcessName,
  SetCustomerNotificationFlag,
} from '../../../../core/store/actions/process.actions';
import { Router, ActivatedRoute } from '@angular/router';
import { Breadcrumb } from '../../../../core/models/breadcrumb.model';
import {
  SetUserDetails,
  SetUserDetailsById,
  AddNewShippingAddress,
  AddNewInvoiceAddress,
  SetLastCreatedCustomerId,
  ClearLastCustomerCreatedId,
} from '../../../../core/store/actions/customer.actions';
import { AddBreadcrumb } from '../../../../core/store/actions/breadcrumb.actions';
import { takeUntil, filter } from 'rxjs/operators';
import { EditCustomerData } from '../../../../core/models/edit-customer.model';
import { SharedSelectors } from '../../../../core/store/selectors/shared.selectors';
import { ProcessCart } from '../../../../core/models/process-cart.model';
import { CustomValidators } from '../../../../shared/validation/custom-validation';
import { getProperty } from '../../../../core/utils/app.utils';
import { ProcessSelectors } from '../../../../core/store/selectors/process.selectors';
import { isNullOrUndefined } from 'util';
import { CustomerService } from 'apps/sales/src/app/core/services/customer.service';
import { CustomerMapping } from 'apps/sales/src/app/core/mappings/customer.mapping';
import { CustomerSelectors } from 'apps/sales/src/app/core/store/selectors/customer.selectors';
import { CustomerFeatures } from 'apps/sales/src/app/core/models/customer-features.model';

export enum AddressUpdateType {
  ShippingAddressUpdate,
  InvoiceAddressUpdate,
  NoUpdate,
}

@Component({
  selector: 'app-edit-customer-card',
  templateUrl: './customer-edit-card.component.html',
  styleUrls: ['./customer-edit-card.component.scss'],
})
export class CustomerEditCardComponent implements OnInit, OnDestroy {
  @Select(SharedSelectors.getCustomerEditData) customerEditData$: Observable<EditCustomerData>;
  @Select(SharedSelectors.getCart) cartData$: Observable<ProcessCart>;
  destroy$ = new Subject();

  customer: User;
  userForm: FormGroup;
  breadcrumbs: Breadcrumb[] = [];
  sumbited = false;
  isEditing = false;
  cartExist = false;
  features: Features[] = [];
  emailPrevState: string;
  byPassEmailValidation = false;
  userId: number;
  customerFeatures: CustomerFeatures;

  // form state variables
  firstNameNotEditable = false;
  lastNameNotEditable = false;
  billingAddressEditDetails = false;
  deliveryAddressEditDetails = false;
  emailNotEditable = false;
  phoneNotEditable = false;
  mobileNotEditable = false;
  billingAddressEditable = false;
  deliveryAddressEditable = false;
  companyNameNotEditable = false;
  companyAddressNotEditable = false;
  companyDepartmentNotEditable = false;
  companyVatIdNotEditable = false;

  disableAssignment = false;

  constructor(private store: Store, private fb: FormBuilder, private router: Router, private route: ActivatedRoute) {}

  ngOnInit() {
    this.userForm = this.buildForm(this.fb);

    this.route.params.pipe(takeUntil(this.destroy$)).subscribe((params) => {
      this.userId = params['id'];
      this.store.dispatch(new SetUserDetailsById(params['id']));
    });

    this.customerEditData$
      .pipe(
        filter((data) => getProperty(data, 'customer') && getProperty(data, 'breadcrumbs')),
        takeUntil(this.destroy$)
      )
      .subscribe((data: EditCustomerData) => {
        this.processCustomer(data.customer);
        this.customerFeatureSpecificInitializations(this.customerFeatures);
        this.breadcrumbs = data.breadcrumbs;
      });

    this.cartData$
      .pipe(
        filter((data) => getProperty(data, 'cart')),
        takeUntil(this.destroy$)
      )
      .subscribe((processCart: ProcessCart) => {
        this.cartExist = processCart.cart.length > 0 ? true : false;
      });
  }

  hasDownloadAction = () => {
    const hasOnlineAccount = this.features.find((feature) => feature.key === 'onlineshop');
    if (!hasOnlineAccount) {
      this.router.navigate(['/customer/search'], {
        queryParams: { card: 'create' },
      });
    }
  };

  private processCustomer(customer: User) {
    this.customer = customer;
    const firstName = customer.first_name;
    const lastName = customer.last_name;
    let invoiceAddress = '';
    let deliveryAddress = '';
    this.features = customer.features && customer.features.length > 0 ? customer.features : [];
    this.customerFeatures = new CustomerFeatures(this.features);

    if (customer.delivery_addres) {
      const street = customer.delivery_addres.street ? customer.delivery_addres.street : '';
      const streetNumber = customer.delivery_addres.streetNo ? customer.delivery_addres.streetNo : '';
      const zip = customer.delivery_addres.zip ? customer.delivery_addres.zip : '';
      const city = customer.delivery_addres.city ? customer.delivery_addres.city : '';

      const comma = !!zip && !!streetNumber ? ',' : '';

      deliveryAddress = `${street} ${streetNumber}${comma} ${zip} ${city}`;
    }

    if (customer.invoice_address) {
      const street = customer.invoice_address.street ? customer.invoice_address.street : '';
      const streetNumber = customer.invoice_address.streetNo ? customer.invoice_address.streetNo : '';
      const zip = customer.invoice_address.zip ? customer.invoice_address.zip : '';
      const city = customer.invoice_address.city ? customer.invoice_address.city : '';

      const comma = !!zip && !!streetNumber ? ',' : '';

      invoiceAddress = `${street} ${streetNumber}${comma} ${zip} ${city}`;
    }

    this.emailPrevState = customer.email;

    let organisationName: string;
    let organisationExtraAddress: string;
    let organisationDepartment: string;
    let organisationVatId: string;
    if (customer.organisation) {
      organisationName = customer.organisation.name;
      organisationExtraAddress = customer.organisation.extraAddress;
      organisationDepartment = customer.organisation.department;
      organisationVatId = customer.organisation.vatId;
    }

    this.setInputData('first_name', firstName);
    this.setInputData('last_name', lastName);
    this.setInputData('email', customer.email);
    this.setInputData('mobile_number', customer.mobile_number);
    this.setInputData('phone_number', customer.phone_number);
    this.setInputData('invoice_addrees', invoiceAddress);
    this.setInputData('delivery_address', deliveryAddress);
    this.setInputData('company_name', organisationName);
    this.setInputData('company_address', organisationExtraAddress);
    this.setInputData('company_department', organisationDepartment);
    this.setInputData('company_vatId', organisationVatId);
    this.companyValidators();
  }

  customerFeatureSpecificInitializations(customerFeatures: CustomerFeatures) {
    customerFeatures.online.ifTrue(this.onlineState);
    customerFeatures.guest.ifTrue(this.guestState);
    customerFeatures.employee.ifTrue(this.employeeState);
    (customerFeatures.card && !customerFeatures.online && !customerFeatures.guest && !customerFeatures.employee).ifTrue(this.cardState);
  }

  onlineState = () => {
    this.firstNameNotEditable = true;
    this.lastNameNotEditable = true;
    this.emailNotEditable = true;
    this.billingAddressEditDetails = true;
    this.deliveryAddressEditDetails = true;
    this.phoneNotEditable = true;
    this.mobileNotEditable = true;
    this.billingAddressEditable = false;
    this.deliveryAddressEditable = false;
    this.companyNameNotEditable = true;
    this.companyAddressNotEditable = true;
    this.companyDepartmentNotEditable = true;
    this.companyVatIdNotEditable = true;
    this.disableAssignment = false;
  };

  guestState = () => {
    const lastCreatedCustomerId = this.store.selectSnapshot(CustomerSelectors.getCustomerLastCreatedCustomerId);
    (+this.customer.id === +lastCreatedCustomerId).ifFalse(() => {
      this.firstNameNotEditable = true;
      this.lastNameNotEditable = true;
      this.emailNotEditable = true;
      this.phoneNotEditable = true;
      this.mobileNotEditable = true;
      this.billingAddressEditable = true;
      this.deliveryAddressEditable = true;
      this.companyNameNotEditable = true;
      this.companyAddressNotEditable = true;
      this.companyDepartmentNotEditable = true;
      this.companyVatIdNotEditable = true;
      this.disableAssignment = true;
    });
  };

  employeeState = () => {
    this.firstNameNotEditable = true;
    this.lastNameNotEditable = true;
    this.emailNotEditable = true;
    this.phoneNotEditable = true;
    this.mobileNotEditable = true;
    this.billingAddressEditable = true;
    this.deliveryAddressEditable = false;
    this.deliveryAddressEditDetails = true;
    this.companyNameNotEditable = true;
    this.companyAddressNotEditable = true;
    this.companyDepartmentNotEditable = true;
    this.companyVatIdNotEditable = true;
    this.disableAssignment = false;
  };

  cardState = () => {
    this.emailNotEditable = true;
  };

  companyValidators() {
    const extraAddress = this.userForm.get('company_address').value ? this.userForm.get('company_address').value : null;
    const department = this.userForm.get('company_department').value ? this.userForm.get('company_department').value : null;
    const vatId = this.userForm.get('company_vatId').value ? this.userForm.get('company_vatId').value : null;
    if (!isNullOrUndefined(extraAddress) || !isNullOrUndefined(department) || !isNullOrUndefined(vatId)) {
      this.userForm.get('company_name').setValidators([Validators.required]);
      this.userForm.get('company_name').updateValueAndValidity();
    } else {
      this.userForm.get('company_name').clearValidators();
      this.userForm.get('company_name').updateValueAndValidity();
    }
  }

  enableInput(field: string, input: any) {
    this.byPassEmailValidation = false;
    const control = this.userForm.get(field);

    if (field === 'email') {
      const controlValueEmpty = isNullOrUndefined(control.value) || control.value === '';
      if (isNullOrUndefined(this.emailPrevState) && controlValueEmpty) {
        this.byPassEmailValidation = true;
      }
    }

    if (control.disabled && !this.isEditing) {
      control.enable();
      input.focus();
      this.isEditing = true;
    } else {
      this.sumbited = true;
      if (control.valid || this.byPassEmailValidation) {
        if (field === 'email') {
          this.emailPrevState = control.value;
        }
        const updateCustomer = this.updateCustomerData();
        this.store.dispatch(new SetUserDetails(updateCustomer));
        control.disable();
        this.sumbited = false;
        this.isEditing = false;
      }
    }
  }

  updateCustomerData(): User {
    const updateCustomer: User = { ...this.customer };

    updateCustomer.first_name = this.userForm.get('first_name').value ? this.userForm.get('first_name').value : null;
    updateCustomer.last_name = this.userForm.get('last_name').value ? this.userForm.get('last_name').value : null;
    updateCustomer.email = this.userForm.get('email').value ? this.userForm.get('email').value : null;
    updateCustomer.mobile_number = this.userForm.get('mobile_number').value ? this.userForm.get('mobile_number').value : null;
    updateCustomer.phone_number = this.userForm.get('phone_number').value ? this.userForm.get('phone_number').value : null;
    const companyName = this.userForm.get('company_name').value ? this.userForm.get('company_name').value : undefined;
    const extraAddress = this.userForm.get('company_address').value ? this.userForm.get('company_address').value : undefined;
    const department = this.userForm.get('company_department').value ? this.userForm.get('company_department').value : undefined;
    const vatId = this.userForm.get('company_vatId').value ? this.userForm.get('company_vatId').value : undefined;
    if (!isNullOrUndefined(companyName)) {
      updateCustomer.organisation = {
        name: companyName,
        extraAddress: extraAddress,
        department: department,
        vatId: vatId,
      };
    } else {
      updateCustomer.organisation = undefined;
    }
    return updateCustomer;
  }

  shoppingCart() {
    const newBread: Breadcrumb = {
      name: 'Warenkorb',
      path: '/cart/review',
    };
    const userSet = this.setUserInStore();
    userSet.ifTrue(() => this.navigate(newBread, 'shoppingCart', true));
  }

  articleSearch() {
    const newBread: Breadcrumb = {
      name: 'Artikelsuche',
      path: '/product/search',
    };
    const userSet = this.setUserInStore();
    userSet.ifTrue(() => this.navigate(newBread, 'product', true));
  }

  private setUserInStore() {
    if (this.customer && this.customer.id && this.customer.last_name) {
      this.updateAddressessIfNeededAndPossible();
      this.store.dispatch(new SetLastCreatedCustomerId());
      // TODO: HIMA-965 fix; check if no other workflows are not effected
      // this.store.dispatch(new SetUserDetailsById(this.userId));
      this.store.dispatch(new SetActiveCustomer(this.customer.id));
      this.store.dispatch(new UpdateProcessName(this.customer.last_name));
      this.store.dispatch(new SetCustomerNotificationFlag(false));
      return true;
    }
    return false;
  }

  private updateAddressessIfNeededAndPossible() {
    if (!this.customer.delivery_addres && this.customer.invoice_address) {
      this.store.dispatch(
        new AddNewShippingAddress(this.customer.id, {
          ...this.customer.invoice_address,
          id: undefined,
        })
      );
    }

    if (this.customer.delivery_addres && !this.customer.invoice_address) {
      this.store.dispatch(
        new AddNewInvoiceAddress(this.customer.id, {
          ...this.customer.delivery_addres,
          id: undefined,
        })
      );
    }
  }

  private navigate(bread: Breadcrumb, menu: string, reset = false, queryParams?: any) {
    this.store.dispatch(new AddBreadcrumb(bread, menu, reset));
    this.store.dispatch(new ChangeCurrentRoute(bread.path));
    this.router.navigate([`/${bread.path}`], {
      queryParams: queryParams ? queryParams : {},
    });
  }

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

  navigateToBillingAddress() {
    const queryParams = this.billingAddressEditDetails ? { notEditable: true } : undefined;
    const newBread: Breadcrumb = {
      name: 'Rechnungsadresse',
      path: '/customer/edit/' + this.customer.id + '/billing',
      queryParams: queryParams,
    };

    this.navigate(newBread, 'customer', false, queryParams);
  }

  navigateToDeliveryAddress() {
    const queryParams = this.deliveryAddressEditDetails ? { notEditable: true } : undefined;
    const newBread: Breadcrumb = {
      name: 'Lieferadresse',
      path: '/customer/edit/' + this.customer.id + '/delivery',
      queryParams: queryParams,
    };

    this.navigate(newBread, 'customer', false, queryParams);
  }

  private setInputData(field: string, val: string) {
    this.userForm.get(field).patchValue(val);
    this.userForm.get(field).disable();
  }

  get f() {
    return this.userForm.controls;
  }

  private buildForm(fb: FormBuilder) {
    return fb.group({
      first_name: ['', Validators.required],
      last_name: ['', Validators.required],
      email: ['', [Validators.required, CustomValidators.validateEmail]],
      mobile_number: ['', [CustomValidators.validateTelephone]],
      phone_number: ['', [CustomValidators.validateTelephone]],
      invoice_addrees: [''],
      delivery_address: [''],
      company_name: [''],
      company_address: [''],
      company_department: [''],
      company_vatId: [''],
    });
  }

  ngOnDestroy(): void {
    this.destroy$.next();
  }
}
