import { Component, ChangeDetectionStrategy, Input, OnInit, ChangeDetectorRef } from '@angular/core';
import { UntypedFormControl, UntypedFormGroup } from '@angular/forms';
import { CrmCustomerService } from '@domain/crm';
import { CountryDTO } from '@generated/swagger/crm-api';
import { camelCase } from 'lodash';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { FormBlockGroup } from '../form-block';
import { AddressFormBlockData } from './address-form-block-data';

@Component({
  selector: 'app-address-form-block',
  templateUrl: 'address-form-block.component.html',
  styleUrls: ['address-form-block.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: false,
})
export class AddressFormBlockComponent extends FormBlockGroup<AddressFormBlockData> implements OnInit {
  @Input() countries: CountryDTO[];

  @Input() defaults: Partial<AddressFormBlockData>;

  get tabIndexEnd(): number {
    return this.tabIndexStart + 5;
  }

  countries$: Observable<CountryDTO[]>;

  constructor(
    private readonly _customerService: CrmCustomerService,
    private _cdr: ChangeDetectorRef,
  ) {
    super();
  }

  ngOnInit(): void {
    super.ngOnInit();

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

  initializeControl(data?: AddressFormBlockData): void {
    this.control = new UntypedFormGroup({
      country: new UntypedFormControl(data?.country ?? this.defaults?.country ?? '', this.getValidatorFn('country')),
      city: new UntypedFormControl(data?.city ?? this.defaults?.city ?? '', this.getValidatorFn('city')),
      street: new UntypedFormControl(data?.street ?? this.defaults?.street ?? '', this.getValidatorFn('street')),
      streetNumber: new UntypedFormControl(
        data?.streetNumber ?? this.defaults?.streetNumber ?? '',
        this.getValidatorFn('streetNumber'),
      ),
      zipCode: new UntypedFormControl(data?.zipCode ?? this.defaults?.zipCode ?? '', this.getValidatorFn('zipCode')),
      info: new UntypedFormControl(data?.info ?? this.defaults?.info ?? '', this.getValidatorFn('info')),
    });
  }

  _patchValue(update: { previous: AddressFormBlockData; current: AddressFormBlockData }): void {
    this.control.patchValue({
      country: update.current.country ?? '',
      city: update.current.city ?? '',
      street: update.current.street ?? '',
      streetNumber: update.current.streetNumber ?? '',
      zipCode: update.current.zipCode ?? '',
      info: update.current.info ?? '',
    });
  }

  setAddressValidationError(invalidProperties: Record<keyof AddressFormBlockData, string>) {
    const keys = Object.keys(invalidProperties);
    for (const key of keys) {
      this.control.get(camelCase(key))?.setErrors({ validateAddress: invalidProperties[key] });
    }
    this.control.markAllAsTouched();
    this._cdr.markForCheck();
  }

  updateValidators(): void {
    this.control.get('country')?.setValidators(this.getValidatorFn('country'));
    this.control.get('city')?.setValidators(this.getValidatorFn('city'));
    this.control.get('street')?.setValidators(this.getValidatorFn('street'));
    this.control.get('streetNumber')?.setValidators(this.getValidatorFn('streetNumber'));
    this.control.get('zipCode')?.setValidators(this.getValidatorFn('zipCode'));
    this.control.get('info')?.setValidators(this.getValidatorFn('info'));
    this.control.updateValueAndValidity();
  }
}
