import { Component, OnInit } from '@angular/core';
import { DetailsFormBase } from '@objects-view/details-form-base';
import { UntypedFormBuilder, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { ConfigService } from '@shared/config/config.service';
import { Observable, of } from 'rxjs';
import { IActionResult } from '@objects-view/interfaces/actions/action-result';
import { IFloatingIpModel } from '@fleio-api/openstack/floating-ips/model/floating-ip.model';
import { FloatingIpsApiService } from '@fleio-api/openstack/floating-ips/floating-ips-api.service';
import { IClientModel } from '@fleio-api/client-user/model/client.model';
import { debounceTime } from 'rxjs/operators';
import { ClientsApiService } from '@fleio-api/client-user/client/clients-api.service';
import { IFloatingIpCreateOptionsModel } from '@fleio-api/openstack/floating-ips/model/floating-ip-create-options.model';
import { NotificationService } from '@shared/ui-api/notification.service';
import { INetworkModel } from '@fleio-api/openstack/model/network.model';

@Component({
  selector: 'app-floating-ip-edit-form',
  templateUrl: './floating-ip-edit-form.component.html',
  styleUrls: ['./floating-ip-edit-form.component.scss']
})
export class FloatingIpEditFormComponent extends DetailsFormBase<IFloatingIpModel> implements OnInit {
  floatingIpForm = this.formBuilder.group({
    region: [''],
    floating_network: ['', Validators.required],
    description: [''],
  });
  createOptions: IFloatingIpCreateOptionsModel;
  filteredNetworks$: Observable<INetworkModel[]>;
  hasNetworks = false;
  selectClient = false;
  createInClientProject = true;
  relatedInstanceId = null;
  preselectedRegion = null;
  estimatedCost: string;
  estimatedCostLoading = false;

  constructor(
    private formBuilder: UntypedFormBuilder,
    private floatingIpsApiService: FloatingIpsApiService,
    private router: Router,
    public config: ConfigService,
    private clientsApiService: ClientsApiService,
    private notificationService: NotificationService,
    private activatedRoute: ActivatedRoute,
  ) {
    super();
  }

  changeDestination(value) {
    // createInClientProject
    if (value === false) {
      this.floatingIpForm.controls.client.setValue('');
      this.floatingIpForm.controls.client.clearValidators();
      this.floatingIpForm.controls.client.reset();
      this.refreshCreateOptionsWithoutClient();
    } else {
      this.floatingIpForm.controls.client.setValidators(Validators.required);
      // in this case, reset create options
      this.createOptions = null;
      this.floatingIpForm.controls.region.setValue(null);
    }
    this.estimatedCost = null;
  }

  refreshCreateOptionsWithoutClient() {
    this.objectController.loading = true;
    this.floatingIpsApiService.createOptions().subscribe(
      (createOptions: IFloatingIpCreateOptionsModel) => {
        this.createOptions = createOptions;
        if (this.preselectedRegion) {
          this.floatingIpForm.controls.region.setValue(this.preselectedRegion);
        } else {
          this.floatingIpForm.controls.region.setValue(this.createOptions.default_region);
        }
        this.objectController.loading = false;
      }
    );
  }

  ngOnInit() {
    super.ngOnInit();
    if (this.objectController) {
      this.objectController.actionCallback = () => this.floatingIpActions();
    }

    if (this.config.authService.feature('ui.openstack.floating-ips.client')) {
      this.selectClient = true;
      this.floatingIpForm.addControl('client', this.formBuilder.control('', Validators.required));
    }

    if (this.object) {
      this.floatingIpForm.patchValue(this.object);
    }

    const clientID = this.activatedRoute.snapshot.params?.clientid || null;
    this.relatedInstanceId = this.activatedRoute.snapshot.params?.instanceid || null;
    this.preselectedRegion = this.activatedRoute.snapshot.params?.region || null;
    if (this.relatedInstanceId && this.preselectedRegion && !clientID) {
      // if params are as in the above if clause, there is no client, and we can select admin project
      this.createInClientProject = false;
      this.changeDestination(this.createInClientProject);
    }

    if (this.selectClient) {
      this.floatingIpForm.controls.client.valueChanges.subscribe(client => {
        if (client && client.id) {
          const clientObj = client as IClientModel;
          this.objectController.loading = true;
          this.floatingIpsApiService.createOptions({client_id: clientObj.id}).subscribe(
            (createOptions: IFloatingIpCreateOptionsModel) => {
              this.createOptions = createOptions;
              if (!this.preselectedRegion) {
                this.floatingIpForm.controls.region.setValue(this.createOptions.default_region);
              } else {
                this.floatingIpForm.controls.region.setValue(this.preselectedRegion);
                const networkID = this.activatedRoute.snapshot.params?.networkid || null;
                if (networkID) {
                  this.floatingIpForm.controls.floating_network.setValue(networkID);
                }
              }
              this.objectController.loading = false;
            }
          );
        }
      });
      if (clientID) {
        this.clientsApiService.get(clientID).subscribe(client => {
          this.floatingIpForm.controls.client.setValue(client);
        });
      }
    } else {
      this.refreshCreateOptionsWithoutClient();
    }

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

    this.floatingIpForm.controls.region.valueChanges.subscribe(region => {
      if (this.createOptions) {
        const networks = this.createOptions.networks.filter(network => network.region === region);
        this.hasNetworks = networks.length > 0;
        this.filteredNetworks$ = of(networks);
      } else {
        this.hasNetworks = false;
        this.filteredNetworks$ = of([]);
      }
    });
  }

  floatingIpActions(): Observable<IActionResult> {
    const value = this.floatingIpForm.value as any;
    if (value.client && value.client.id) {
      value.client = value.client.id;
    }

    if (!this.hasNetworks) {
      this.formErrors.showError($localize`No network selected.`);
    }

    if (!this.object.id && !this.createInClientProject) {
      value.create_as_admin = true;
    }

    this.createOrUpdate(
      this.floatingIpsApiService,
      value,
    ).subscribe(() => {
      if (this.relatedInstanceId) {
        this.router.navigateByUrl(
          this.config.getPanelUrl(`openstack/instances/${this.relatedInstanceId}#networking`)
        ).catch(() => {
        });
        this.notificationService.showMessage($localize`Floating IP created. Try again to add floating IP to instance.`);
      } else {
        this.redirectAfterCreate('openstack/floating-ips', this.router, this.config);
        this.notificationService.showMessage($localize`Floating IP created`);
      }
      return null;
    });

    return of(null);
  }

  getSimulatedPrice() {
    if (this.config.authService.feature('openstack.floatingips.show-price-on-create')) {
      let clientId = null;
      if (this.selectClient) {
        clientId = this.floatingIpForm.controls.client.value?.id;
      }
      const region = this.floatingIpForm.controls.region.value;
      if (region && ((this.selectClient && clientId) || !this.selectClient)) {
        const params = {
          region,
        } as any;
        if (clientId) {
          params.client_id = clientId;
        }
        this.estimatedCostLoading = true;
        this.floatingIpsApiService.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;
        });
      }
    }
  }
}
