import { Component, ChangeDetectionStrategy, OnInit, OnDestroy, ChangeDetectorRef, inject } 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, PayerDTO } 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 { ComponentStore } from '@ngrx/component-store';
import { Subject, combineLatest } from 'rxjs';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { UiModalService } from '@ui/modal';
import { IconComponent } from '@shared/components/icon';
import { zipCodeValidator } from '../../validators/zip-code-validator';
import { GenderSettingsService } from '@shared/services/gender';

export interface EditBillingAddressMainViewState {
  payer?: PayerDTO;
}

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

  private _onDestroy$ = new Subject<void>();

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

  private _cdr = inject(ChangeDetectorRef);

  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),
    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));

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

  get payerId() {
    return this.get((s) => s.payer?.id);
  }

  get payer() {
    return this.get((s) => s.payer);
  }

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

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

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

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

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

  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 payer: PayerDTO = {
        ...this.payer,
        gender: formData.gender,
        title: formData.title,
        firstName: formData.firstName,
        lastName: formData.lastName,
        organisation: formData.organisation ? { name: formData.organisation } : undefined,
        address: addressValidationResult,
      };

      const result = await this._customerService
        .updatePayer(this._store.customerId, this.payerId, payer, formData.isDefault)
        .toPromise();

      this._navigation.navigateToDetails({ processId: this._store.processId, customerId: this._store.customerId });
    } catch (error) {
      this.formGroup.enable();
      this._modal.error('Fehler beim speichern der Rechnungsadresse', error);
    }
  }
}
