/**
 * Copyright (c) HashiCorp, Inc.
 * SPDX-License-Identifier: MPL-2.0
 */

import Model, { attr } from '@ember-data/model';
import { withModelValidations } from 'vault/decorators/model-validations';
import { withFormFields } from 'vault/decorators/model-form-fields';
import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities';
import { tracked } from '@glimmer/tracking';

const validations = {
  name: [{ type: 'presence', message: 'Name is required' }],
};
const formFieldProps = [
  'name',
  'serviceAccountName',
  'kubernetesRoleType',
  'kubernetesRoleName',
  'allowedKubernetesNamespaces',
  'tokenMaxTtl',
  'tokenDefaultTtl',
  'nameTemplate',
];

@withModelValidations(validations)
@withFormFields(formFieldProps)
export default class KubernetesRoleModel extends Model {
  @attr('string') backend; // dynamic path of secret -- set on response from value passed to queryRecord
  @attr('string', {
    label: 'Role name',
    subText: 'The role’s name in Vault.',
  })
  name;

  @attr('string', {
    label: 'Service account name',
    subText: 'Vault will use the default template when generating service accounts, roles and role bindings.',
  })
  serviceAccountName;

  @attr('string', {
    label: 'Kubernetes role type',
    editType: 'radio',
    possibleValues: ['Role', 'ClusterRole'],
  })
  kubernetesRoleType;

  @attr('string', {
    label: 'Kubernetes role name',
    subText: 'Vault will use the default template when generating service accounts, roles and role bindings.',
  })
  kubernetesRoleName;

  @attr('string', {
    label: 'Service account name',
    subText: 'Vault will use the default template when generating service accounts, roles and role bindings.',
  })
  serviceAccountName;

  @attr('string', {
    label: 'Allowed Kubernetes namespaces',
    subText:
      'A list of the valid Kubernetes namespaces in which this role can be used for creating service accounts. If set to "*" all namespaces are allowed.',
  })
  allowedKubernetesNamespaces;

  @attr({
    label: 'Max Lease TTL',
    editType: 'ttl',
  })
  tokenMaxTtl;

  @attr({
    label: 'Default Lease TTL',
    editType: 'ttl',
  })
  tokenDefaultTtl;

  @attr('string', {
    label: 'Name template',
    editType: 'optionalText',
    defaultSubText:
      'Vault will use the default template when generating service accounts, roles and role bindings.',
    subText: 'Vault will use the default template when generating service accounts, roles and role bindings.',
  })
  nameTemplate;

  @attr extraAnnotations;
  @attr extraLabels;

  @attr('string') generatedRoleRules;

  @tracked _generationPreference;
  get generationPreference() {
    // when the user interacts with the radio cards the value will be set to the pseudo prop which takes precedence
    if (this._generationPreference) {
      return this._generationPreference;
    }
    // for existing roles, default the value based on which model prop has value -- only one can be set
    let pref = null;
    if (this.serviceAccountName) {
      pref = 'basic';
    } else if (this.kubernetesRoleName) {
      pref = 'expanded';
    } else if (this.generatedRoleRules) {
      pref = 'full';
    }
    return pref;
  }
  set generationPreference(pref) {
    // unset model props specific to filteredFormFields when changing preference
    // only one of service_account_name, kubernetes_role_name or generated_role_rules can be set
    const props = {
      basic: ['kubernetesRoleType', 'kubernetesRoleName', 'generatedRoleRules', 'nameTemplate'],
      expanded: ['serviceAccountName', 'generatedRoleRules'],
      full: ['serviceAccountName', 'kubernetesRoleName'],
    }[pref];
    props.forEach((prop) => (this[prop] = null));
    this._generationPreference = pref;
  }

  get filteredFormFields() {
    // return different form fields based on generationPreference
    const hiddenFieldIndices = {
      basic: [2, 3, 7], // kubernetesRoleType, kubernetesRoleName and nameTemplate
      expanded: [1], // serviceAccountName
      full: [1, 3], // serviceAccountName and kubernetesRoleName
    }[this.generationPreference];

    return hiddenFieldIndices
      ? this.formFields.filter((field, index) => !hiddenFieldIndices.includes(index))
      : null;
  }

  @lazyCapabilities(apiPath`${'backend'}/roles/${'name'}`, 'backend', 'name') rolePath;
  @lazyCapabilities(apiPath`${'backend'}/creds/${'name'}`, 'backend', 'name') credsPath;
  @lazyCapabilities(apiPath`${'backend'}/roles`, 'backend') rolesPath;

  get canCreate() {
    return this.rolePath.get('canCreate');
  }
  get canDelete() {
    return this.rolePath.get('canDelete');
  }
  get canEdit() {
    return this.rolePath.get('canUpdate');
  }
  get canRead() {
    return this.rolePath.get('canRead');
  }
  get canList() {
    return this.rolesPath.get('canList');
  }
  get canGenerateCreds() {
    return this.credsPath.get('canCreate');
  }
}
