import {
  Component,
  ChangeDetectionStrategy,
  OnInit,
  OnDestroy,
  inject,
  ChangeDetectorRef,
} from '@angular/core';
import { CheckboxComponent } from '@shared/components/checkbox';
import { FormControl, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
import { SelectModule } from '@shared/components/select';
import { FormControlComponent } from '@shared/components/form-control';
import { CrmCustomerService } from '@domain/crm';
import { AddressDTO, Gender, ShippingAddressDTO } from '@generated/swagger/crm-api';
import { map, switchMap, takeUntil } from 'rxjs/operators';
import { AsyncPipe } from '@angular/common';
import { AddressSelectionModalService } from '@modal/address-selection';
import { CustomerSearchStore } from '../store';
import { CustomerSearchNavigation } from '@shared/services/navigation';
import { Subject, combineLatest } from 'rxjs';
import { IconComponent } from '@shared/components/icon';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { ComponentStore } from '@ngrx/component-store';
import { zipCodeValidator } from '../../validators/zip-code-validator';
import { GenderSettingsService } from '@shared/services/gender';
import { validateCompanyOrPersonalInfoRequired } from '../../validators/gender-b2b-validator';

export interface EditShippingAddressMainViewState {
  shippingAddress?: ShippingAddressDTO;
}

@Component({
  selector: 'page-edit-shipping-address-main-view',
  templateUrl: 'edit-shipping-address-main-view.component.html',
  styleUrls: ['edit-shipping-address-main-view.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  host: { class: 'page-edit-shipping-address-main-view' },
  imports: [
    IconComponent,
    RouterLink,
    AsyncPipe,
    ReactiveFormsModule,
    SelectModule,
    FormControlComponent,
    CheckboxComponent
],
})
export class EditShippingAddressMainViewComponent
  extends ComponentStore<EditShippingAddressMainViewState>
  implements OnInit, OnDestroy
{
  private _activatedRoute = inject(ActivatedRoute);
  private _customerService = inject(CrmCustomerService);
  private _addressSelection = inject(AddressSelectionModalService);
  private _store = inject(CustomerSearchStore);
  private _navigation = inject(CustomerSearchNavigation);
  public genderSettings = inject(GenderSettingsService);

  private _onDestroy = new Subject<void>();

  private _cdr = inject(ChangeDetectorRef);

  detailsRoute$ = combineLatest([this._store.processId$, this._store.customerId$]).pipe(
    map(([processId, customerId]) => this._navigation.detailsRoute({ processId, customerId })),
  );

  formGroup = new FormGroup({
    gender: new FormControl<Gender>(undefined, [Validators.required]),
    title: new FormControl<string>(undefined),
    firstName: new FormControl<string>(undefined, [Validators.required]),
    lastName: new FormControl<string>(undefined, [Validators.required]),
    organisation: new FormControl<string>(undefined),
    department: new FormControl<string>(undefined),
    vatId: new FormControl<string>(undefined),
    street: new FormControl<string>(undefined, [Validators.required]),
    streetNumber: new FormControl<string>(undefined, [Validators.required]),
    zipCode: new FormControl<string>(undefined, [Validators.required, zipCodeValidator()]),
    city: new FormControl<string>(undefined, [Validators.required]),
    country: new FormControl<string>('DEU', [Validators.required]),
    info: new FormControl<string>(undefined),
    isDefault: new FormControl<boolean>(false),
  });

  countries$ = this._customerService.getCountries().pipe(map((res) => res.result));

  isBusinessKonto$ = this._store.isBusinessKonto$;

  shippingAddressId$ = this._activatedRoute.params.pipe(
    map((params) => params.shippingAddressId),
    switchMap((shippingAddressId) =>
      this._customerService.getShippingAddress(shippingAddressId).pipe(map((res) => res.result)),
    ),
  );

  get shippingAddressId() {
    return this.get((s) => s.shippingAddress?.id);
  }

  constructor() {
    super({ shippingAddress: undefined });
  }

  ngOnInit() {
    this.shippingAddressId$.pipe(takeUntil(this._onDestroy)).subscribe((shippingAddress) => {
      this.patchState({ shippingAddress });
      this.patchFormGroup(shippingAddress);
    });

    this._store.customer$.pipe(takeUntil(this._onDestroy)).subscribe(() => {
      if (this._store.isBusinessKonto) {
        this.formGroup.controls.organisation.setValidators([]);
        this.formGroup.controls.firstName.setValidators([]);
        this.formGroup.controls.lastName.setValidators([]);
        this.formGroup.setValidators([validateCompanyOrPersonalInfoRequired]);
      } else {
        this.formGroup.controls.organisation.clearValidators();
        this.formGroup.controls.firstName.setValidators([Validators.required]);
        this.formGroup.controls.lastName.setValidators([Validators.required]);
        this.formGroup.setValidators([]);
      }
    });
  }

  patchFormGroup(shipping: ShippingAddressDTO) {
    this.formGroup.patchValue({
      gender: shipping.gender ?? 0,
      title: shipping.title,
      lastName: shipping.lastName,
      firstName: shipping.firstName,
      organisation: shipping.organisation?.name,
      street: shipping.address.street,
      streetNumber: shipping.address.streetNumber,
      zipCode: shipping.address.zipCode,
      city: shipping.address.city,
      country: shipping.address.country,
      info: shipping.address.info,
    });

    this.formGroup.markAllAsTouched();
    this.formGroup.updateValueAndValidity();
    this._cdr.markForCheck();
  }

  ngOnDestroy() {
    this._onDestroy.next();
    this._onDestroy.complete();
  }

  async save() {
    if (this.formGroup.invalid) {
      this.formGroup.markAllAsTouched();
      return;
    }

    try {
      this.formGroup.disable();

      const formData = this.formGroup.value;

      const address: AddressDTO = {
        street: formData.street,
        streetNumber: formData.streetNumber,
        zipCode: formData.zipCode,
        city: formData.city,
        country: formData.country,
        info: formData.info,
      };

      const addressValidationResult = await this._addressSelection.validateAddress(address);

      if (addressValidationResult === undefined) {
        this.formGroup.enable();
        return;
      }

      const addOrganization = this._store.isBusinessKonto || formData.organisation !== undefined;

      const shippingAddress: ShippingAddressDTO = {
        gender: formData.gender,
        title: formData.title,
        firstName: formData.firstName,
        lastName: formData.lastName,
        organisation: addOrganization
          ? {
              name: formData.organisation,
              department: formData.department,
              vatId: formData.vatId,
            }
          : undefined,
        address: addressValidationResult,
      };

      const result = await this._customerService.updateShippingAddress(
        this._store.customerId,
        this.shippingAddressId,
        shippingAddress,
        formData.isDefault,
      );

      this._navigation.navigateToDetails({
        processId: this._store.processId,
        customerId: this._store.customerId,
      });
    } catch (error) {
      this.formGroup.enable();
    }
  }
}
