import { Component, OnInit, ViewChild } from '@angular/core';
import { DetailsFormBase } from '@objects-view/details-form-base';
import { IDbaasInstanceModel } from '@fleio-api/openstack/model/dbaas-instance.model';
import { UntypedFormArray, UntypedFormBuilder, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { ConfigService } from '@shared/config/config.service';
import { of } from 'rxjs';
import { IFlavorModel } from '@fleio-api/openstack/model/flavor.model';
import { DbaasInstancesApiService } from '@fleio-api/openstack/dbaas/dbaas-instances-api.service';
import { FlavorsAsCardsComponent } from '@shared/fleio-data-controls/flavors-as-cards/flavors-as-cards.component';
import { NotificationService } from '@shared/ui-api/notification.service';
import { IIcon } from '@shared/ui/common/interfaces/icon';
import { debounceTime } from 'rxjs/operators';
import { ValidatorsHelper } from '@shared/ui-api/helpers/validators-helper';

@Component({
  selector: 'app-dbaas-instance-create-form',
  templateUrl: './dbaas-instance-create-form.component.html',
  styleUrls: ['./dbaas-instance-create-form.component.scss']
})
export class DbaasInstanceCreateFormComponent extends DetailsFormBase<IDbaasInstanceModel> implements OnInit {
  @ViewChild('nicsSelect', {static: true}) nicsSelect;
  @ViewChild('flavorsAsCards') flavorsAsCardsComponent: FlavorsAsCardsComponent;
  databaseInstanceForm = this.formBuilder.group({
    name: ['', [Validators.required, Validators.maxLength(255)]],
    region: ['', Validators.required],
    availability_zone: [''],
    locality: [''],
    volume_size: [1, [ValidatorsHelper.requiredIntegerValidator, Validators.max(50), Validators.min(1)]],
    volume_type: [''],
    flavor_id: [''],
    datastore_type: ['', Validators.required],
    datastore_version: ['', Validators.required],
    nics: ['', Validators.required],
    access_is_public: [false],
    access_allowed_cidrs: this.formBuilder.array([]),
    initial_dbs: [false],
    initial_databases: this.formBuilder.array([]),
    initial_user_username: [''],
    initial_user_password: [''],
    client: ['', Validators.required],
  });

  showPassword = false;
  clientControl = this.databaseInstanceForm.controls.client;
  selectClient = false;
  createInClientProject = true;
  estimatedCost: string;
  estimatedCostLoading = false;

  createOptions;
  datastoreVersions = [];
  isPublicInfoIcon: IIcon = {
    name: 'info',
    verticalAlign: 'middle',
    fontSize: '20px',
    marginLeft: '5px',
    marginTop: '9px',
    tooltipDirection: 'right',
    tooltip: $localize`Whether the database service is exposed to the public.`
  };

  constructor(
    private formBuilder: UntypedFormBuilder,
    private router: Router,
    private config: ConfigService,
    private notificationService: NotificationService,
    private dbaasInstancesApiService: DbaasInstancesApiService,
  ) {
    super();
  }

  changeDestination(value) {
    // createInClientProject
    if (value === false) {
      this.clientControl.setValue('', {emitEvent: false});
      this.clientControl.clearValidators();
      this.clientControl.reset(null, {emitEvent: false});
      this.refreshCreateOptions();
    } else {
      this.clientControl.setValidators(Validators.required);
    }
  }

  private createAddress(address = '') {
    return this.formBuilder.group({
      address: [address, Validators.required],
    });
  }

  public addAddress(event) {
    event.preventDefault();
    const addresses = this.databaseInstanceForm.get('access_allowed_cidrs') as UntypedFormArray;
    addresses.push(this.createAddress());
  }

  public removeAddress(index) {
    const addresses = this.databaseInstanceForm.get('access_allowed_cidrs') as UntypedFormArray;
    addresses.removeAt(index);
  }

  private createDatabase(name = '') {
    return this.formBuilder.group({
      name: [name, [Validators.required, Validators.maxLength(255)]],
    });
  }

  public addDatabase(event) {
    event.preventDefault();
    const dbs = this.databaseInstanceForm.get('initial_databases') as UntypedFormArray;
    dbs.push(this.createDatabase());
  }

  public removeDatabase(index) {
    const dbs = this.databaseInstanceForm.get('initial_databases') as UntypedFormArray;
    dbs.removeAt(index);
  }

  private preselectNics() {
    if (this.createOptions.nics.length === 1) {
      this.databaseInstanceForm.controls.nics.setValue(this.createOptions.nics[0].id);
    } else {
      this.databaseInstanceForm.controls.nics.setValue('');
    }
  }

  private preselectDatastoreType() {
    if (this.createOptions && this.createOptions.datastores && this.createOptions.datastores.length) {
      this.databaseInstanceForm.controls.datastore_type.setValue(this.createOptions.datastores[0].type);
    } else {
      this.databaseInstanceForm.controls.datastore_type.setValue('');
    }
  }

  private preselectAvailabilityZone() {
    // preselect if only one option
    if (this.authSvc?.feature('openstack.dbaas.availability_zones')) {
      if (this.createOptions?.availability_zones?.length === 1) {
        this.databaseInstanceForm.controls.availability_zone.setValue(this.createOptions.availability_zones[0]);
      } else {
        this.databaseInstanceForm.controls.availability_zone.setValue('');
      }
    }
  }

  refreshCreateOptions(region = null) {
    const params = {} as any;
    if (region) {
      params.region = region;
    }
    this.dbaasInstancesApiService.createOptions(params).subscribe(response => {
      this.createOptions = response;
      this.preselectNics();
      this.preselectAvailabilityZone();
      this.preselectDatastoreType();
      this.databaseInstanceForm.controls.flavor_id.setValue('');
    });
  }

  ngOnInit(refreshTimerInterval?: number) {
    super.ngOnInit(refreshTimerInterval);
    if (this.objectController) {
      this.objectController.actionCallback = () => this.saveDatabaseInstance();
      if (this.objectController.additionalObjects) {
        this.createOptions = this.objectController.additionalObjects.createOptions;
        if (this.createOptions.selected_region) {
          this.databaseInstanceForm.controls.region.setValue(this.createOptions.selected_region);
        }
        this.preselectNics();
        this.preselectAvailabilityZone();
      }
    }

    if (this.authSvc.feature('ui.enduser')) {
      this.databaseInstanceForm.removeControl('client');
    } else {
      this.selectClient = true;
    }

    this.databaseInstanceForm.controls.region.valueChanges.subscribe(value => {
      this.refreshCreateOptions(value);
    });

    this.databaseInstanceForm.controls.datastore_type.valueChanges.subscribe(newType => {
      this.datastoreVersions = this.createOptions.datastores.find(datastore => datastore.type === newType).versions;
      if (this.datastoreVersions && this.datastoreVersions.length) {
        this.databaseInstanceForm.controls.datastore_version.setValue(this.datastoreVersions[0]);
      } else {
        this.databaseInstanceForm.controls.datastore_version.setValue('');
      }
    });

    this.preselectDatastoreType();

    this.databaseInstanceForm.controls.initial_dbs.valueChanges.subscribe(value => {
      if (value) {
        this.databaseInstanceForm.controls.initial_user_username.setValidators(
          [Validators.required, Validators.maxLength(16)]
        );
        this.databaseInstanceForm.controls.initial_user_password.setValidators(Validators.required);
      } else {
        this.databaseInstanceForm.controls.initial_user_username.clearValidators();
        this.databaseInstanceForm.controls.initial_user_username.updateValueAndValidity();
        this.databaseInstanceForm.controls.initial_user_password.clearValidators();
        this.databaseInstanceForm.controls.initial_user_password.updateValueAndValidity();
      }
    });

    this.databaseInstanceForm.valueChanges.pipe(debounceTime(300)).subscribe(() => {
      this.getSimulatedPrice();
    });
  }

  onFlavorChosen(flavor: IFlavorModel) {
    if (flavor) {
      this.databaseInstanceForm.controls.flavor_id.setValue(flavor.id);
    } else {
      this.databaseInstanceForm.controls.flavor_id.setValue('');
    }
  }

  getSimulatedPrice() {
    if (this.authSvc.feature('openstack.dbaas.show-price-on-create')) {
      const region = this.databaseInstanceForm.controls.region.value;
      const volumeSize = this.databaseInstanceForm.controls.volume_size.value;
      let clientId = null;
      if (this.selectClient) {
        clientId = this.databaseInstanceForm.controls.client.value?.id;
      }
      const flavorId = this.databaseInstanceForm.controls.flavor_id.value;
      const datastoreType = this.databaseInstanceForm.controls.datastore_type.value;
      if (region && volumeSize && flavorId && datastoreType && ((this.selectClient && clientId) || !this.selectClient)) {
        const params = {
          volume_size: volumeSize,
          flavor_id: flavorId,
          datastore: datastoreType,
          region,
        } as any;
        if (clientId) {
          params.client_id = clientId;
        }
        if (this.databaseInstanceForm.contains('availability_zone') && this.databaseInstanceForm.controls.availability_zone.value) {
          params.availability_zone = this.databaseInstanceForm.controls.availability_zone.value;
        }
        this.estimatedCostLoading = true;
        this.dbaasInstancesApiService.getPrice(params).subscribe({
          next: response => {
            this.estimatedCost = response.estimated_cost_display;
          },
          error: error => {
            if (error?.error?.detail) {
              if (this.config.authService.feature('ui.staff')) {
                this.estimatedCost = error.error.detail;
              } else {
                this.estimatedCost = null;
              }
            }
          }
        }).add(() => {
          this.estimatedCostLoading = false;
        });
      }
    }
  }

  saveDatabaseInstance() {
    this.validate();
    if (this.formGroup.invalid) {
      this.displayControlErrors();
      return of(null);
    }
    if (!this.flavorsAsCardsComponent.selectedFlavor) {
      this.notificationService.showMessage($localize`Select a flavor`);
      return of(null);
    }
    const value = JSON.parse(JSON.stringify(this.databaseInstanceForm.value));
    value.nics = [{network_id: value.nics}];
    if (!value.initial_dbs) {
      delete value.initial_user_username;
      delete value.initial_user_password;
      delete value.initial_databases;
    }
    if (this.authSvc.feature('ui.staff')) {
      if (value.client && this.createInClientProject) {
        value.client_id = value.client.id;
        delete value.client;
      }
    }

    this.createOrUpdate(this.dbaasInstancesApiService, value, true).subscribe(() => {
      this.notificationService.showMessage($localize`Create database instance scheduled.`);
      this.router.navigate(
        [this.config.getPanelUrl('openstack/database-instances')],
        {
          queryParamsHandling: 'merge'
        }
      );
    });

    return of(null);
  }

}
