import { Component, OnInit } from '@angular/core';
import { DetailsFormBase } from '@objects-view/details-form-base';
import { INetworkModel } from '@fleio-api/openstack/model/network.model';
import { UntypedFormBuilder, Validators } from '@angular/forms';
import { IRBACPolicyCreateOptionsModel } from '@fleio-api/openstack/rbac-policy/model/rbac-policy-create-options.model';
import { ConfigService } from '@shared/config/config.service';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { ProjectsApiService } from '@fleio-api/openstack/project/projects-api.service';
import { NetworksApiService } from '@fleio-api/openstack/network/networks-api.service';
import { RbacPoliciesApiService } from '@fleio-api/openstack/rbac-policy/rbac-policies-api.service';
import { NotificationService } from '@shared/ui-api/notification.service';
import { Router } from '@angular/router';
import { SubnetPoolsApiService } from '@fleio-api/openstack/subnet-pools/subnet-pools-api.service';
import { SecurityGroupsApiService } from '@fleio-api/openstack/security-groups/security-groups-api.service';
import { ISecurityGroupModel } from '@fleio-api/openstack/model/security-group.model';
import { ISubnetPoolModel } from '@fleio-api/openstack/subnet-pools/model/subnet-pool.model';
import { AutocompleteHelper } from '@shared/ui-api/helpers/autocomplete-helper';

@Component({
  selector: 'app-rbac-policy-create-form',
  templateUrl: './rbac-policy-create-form.component.html',
  styleUrl: './rbac-policy-create-form.component.scss'
})
export class RbacPolicyCreateFormComponent extends DetailsFormBase<INetworkModel> implements OnInit {
  rbacForm = this.formBuilder.group({
    client: [null],
    target_project: ['', Validators.required],
    object_type: ['', Validators.required],
    object_id: ['', Validators.required],
    action: ['', Validators.required],
  });
  clientControl = this.rbacForm.controls.client;
  createOptions: IRBACPolicyCreateOptionsModel;
  createInClientProject = false;
  projectUnselectedPlaceholder = $localize`Select target project ...`;
  projectSelectedPlaceholder = $localize`Target project`;
  networkUnselectedPlaceholder = $localize`Select network ...`;
  networkSelectedPlaceholder = $localize`Network`;
  subnetPoolUnselectedPlaceholder = $localize`Select subnet pool ...`;
  subnetPoolSelectedPlaceholder = $localize`Subnet pool`;
  securityGroupUnselectedPlaceholder = $localize`Select security group ...`;
  securityGroupSelectedPlaceholder = $localize`Security group`;
  projectOptionsSwitchMap: (search: string) => Observable<any>;
  networkOptionsSwitchMap: (search: string) => Observable<any>;
  subnetPoolOptionsSwitchMap: (search: string) => Observable<any>;
  securityGroupOptionsSwitchMap: (search: string) => Observable<any>;

  constructor(
    private formBuilder: UntypedFormBuilder,
    private config: ConfigService,
    private projectsApiService: ProjectsApiService,
    private networksApiService: NetworksApiService,
    private subnetPoolsApiService: SubnetPoolsApiService,
    private securityGroupsApiService: SecurityGroupsApiService,
    private rbacPoliciesApiService: RbacPoliciesApiService,
    private notificationService: NotificationService,
    private router: Router,
  ) {
    super();
  }

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

  ngOnInit() {
    super.ngOnInit();
    if (this.objectController) {
      this.objectController.actionCallback = () => this.saveRBACPolicy();
      this.createOptions = this.objectController.additionalObjects.createOptions as IRBACPolicyCreateOptionsModel;
    }

    this.projectOptionsSwitchMap = (search) => {
      return this.projectsApiService.list({search}).pipe(
        map(data => {
            let response = data.objects as any;
            response.unshift('*');
            return response;
          }
        ));
    };

    this.networkOptionsSwitchMap = (search) => {
      let queryParams = {search} as any;
      const clientId = this.rbacForm.controls.client.value?.id;
      if (clientId) {
        queryParams.filtering = `project__service__client:${clientId}`;
      }
      return this.networksApiService.list(queryParams).pipe(
        map(data => {
            return data.objects;
          }
        ));
    };

    this.subnetPoolOptionsSwitchMap = (search) => {
      let queryParams = {search} as any;
      const clientId = this.rbacForm.controls.client.value?.id;
      if (clientId) {
        queryParams.filtering = `project__service__client:${clientId}`;
      }
      return this.subnetPoolsApiService.list(queryParams).pipe(
        map(data => {
            return data.objects;
          }
        ));
    };

    this.securityGroupOptionsSwitchMap = (search) => {
      let queryParams = {search} as any;
      const clientId = this.rbacForm.controls.client.value?.id;
      if (clientId) {
        queryParams.filtering = `project__service__client:${clientId}`;
      }
      return this.securityGroupsApiService.list(queryParams).pipe(
        map(data => {
            return data.objects;
          }
        ));
    };

    this.rbacForm.controls.object_type.valueChanges.subscribe(() => {
      this.rbacForm.controls.object_id.setValue(null);
    });

    this.rbacForm.controls.client.valueChanges.subscribe(value => {
      AutocompleteHelper.refreshAutocompleteOptions(this.rbacForm.controls.object_id);
    });
  }

  networkDisplay(network?: INetworkModel): string | undefined {
    if (network) {
      return network.name ? `${network.name} - ${network.region}` : `${network.id.toString()} - ${network.region}`;
    } else {
      return undefined;
    }
  }

  securityGroupDisplay(securityGroup?: ISecurityGroupModel): string | undefined {
    if (securityGroup) {
      return securityGroup.name ? `${securityGroup.name} - ${securityGroup.id.toString()} - ${securityGroup.region}` :
        `${securityGroup.id.toString()} - ${securityGroup.region}`;
    } else {
      return undefined;
    }
  }

  subnetPoolDisplay(subnetPool?: ISubnetPoolModel): string | undefined {
    if (subnetPool) {
      return subnetPool.name ? `${subnetPool.name} - ${subnetPool.id.toString()} - ${subnetPool.region}` :
        `${subnetPool.id.toString()} - ${subnetPool.region}`;
    } else {
      return undefined;
    }
  }

  saveRBACPolicy() {
    this.validate();
    if (this.rbacForm.invalid) {
      this.displayControlErrors();
      return of(null);
    }
    const value = JSON.parse(JSON.stringify(this.rbacForm.value));
    if (value.object_id?.id) {
      value.object_id = value.object_id.id;
    }
    if (value.target_project?.project_id) {
      value.target_project = value.target_project.project_id;
    }
    if (value.client?.id) {
      value.client = value.client.id;
    } else {
      value.client = null;
    }

    this.objectController.loading = true;
    this.rbacPoliciesApiService.create(value).subscribe({
      next: () => {
        this.objectController.loading = false;
        this.redirectAfterCreate('openstack/rbac-policies', this.router, this.config);
        this.notificationService.showMessage($localize`RBAC policy created`);
      },
      error: error => {
        this.objectController.loading = false;
        if (error.error) {
          this.setErrors(error.error);
        }
      }
    });
    return of(null);
  }

}
