<!--

    Copyright © 2016-2026 The Thingsboard Authors

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

-->
<div>
  <mat-card appearance="outlined" class="settings-card">
    <mat-card-header>
      <mat-card-title>
        <span class="mat-headline-5" translate>admin.2fa.2fa</span>
      </mat-card-title>
      <span class="flex-1"></span>
      <div tb-help="twoFactorAuthentication"></div>
    </mat-card-header>
    @if (isLoading$ | async) {
      <mat-progress-bar color="warn" mode="indeterminate">
      </mat-progress-bar>
    }
    @if (!(isLoading$ | async)) {
      <div style="height: 4px;"></div>
    }
    <mat-card-content>
      <form [formGroup]="twoFaFormGroup" (ngSubmit)="save()">
        <fieldset [disabled]="isLoading$ | async">
          <div class="tb-form-panel no-padding no-border">
            <div class="tb-form-panel stroked tb-slide-toggle">
              <mat-expansion-panel class="tb-settings no-padding-bottom">
                <mat-expansion-panel-header>
                  <mat-panel-title>
                    <mat-slide-toggle class="mat-slide flex items-center justify-start"
                                      (mousedown)="toggleExtensionPanel($event, 0, twoFaFormGroup.get('enforceTwoFa').value)"
                                      formControlName="enforceTwoFa">
                      {{ 'admin.2fa.force-2fa' | translate }}
                    </mat-slide-toggle>
                  </mat-panel-title>
                </mat-expansion-panel-header>
                <ng-template matExpansionPanelContent>
                  <section class="tb-form-panel no-padding no-border" formGroupName="enforcedUsersFilter">
                    <mat-form-field class="mat-block" appearance="outline" subscriptSizing="dynamic">
                      <mat-label translate>admin.2fa.enforce-for</mat-label>
                      <mat-select formControlName="type">
                        @for (type of notificationTargetConfigTypes; track type) {
                          <mat-option [value]="type">
                            {{ notificationTargetConfigTypeInfoMap.get(type).name | translate }}
                          </mat-option>
                        }
                      </mat-select>
                    </mat-form-field>
                    @if (twoFaFormGroup.get('enforcedUsersFilter.type').value === notificationTargetConfigType.TENANT_ADMINISTRATORS) {
                      <section class="tb-form-panel no-padding no-border">
                        <div class="flex flex-1 items-center justify-center">
                          <tb-toggle-select class="tb-notification-tenant-group" appearance="fill"
                                            formControlName="filterByTenants">
                            <tb-toggle-option [value]="true">{{ 'tenant.tenant' | translate }}</tb-toggle-option>
                            <tb-toggle-option [value]="false">{{ 'tenant-profile.tenant-profile' | translate }}</tb-toggle-option>
                          </tb-toggle-select>
                        </div>
                        @if (twoFaFormGroup.get('enforcedUsersFilter.filterByTenants').value) {
                          <tb-entity-list
                            formControlName="tenantsIds"
                            subscriptSizing="dynamic"
                            appearance="outline"
                            labelText="{{ 'tenant.tenants' | translate }}"
                            placeholderText="{{ 'tenant.tenants' | translate }}"
                            hint="{{ 'notification.tenants-list-rule-hint' | translate }}"
                            [entityType]="entityType.TENANT">
                          </tb-entity-list>
                        } @else {
                          <tb-entity-list
                            formControlName="tenantProfilesIds"
                            subscriptSizing="dynamic"
                            appearance="outline"
                            labelText="{{ 'tenant-profile.tenant-profiles' | translate }}"
                            placeholderText="{{ 'tenant-profile.tenant-profiles' | translate }}"
                            hint="{{ 'notification.tenant-profiles-list-rule-hint' | translate }}"
                            [entityType]="entityType.TENANT_PROFILE">
                          </tb-entity-list>
                        }
                      </section>
                    }
                  </section>
                </ng-template>
              </mat-expansion-panel>
            </div>

            <section class="tb-form-panel stroked" formArrayName="providers">
              <div class="tb-form-panel-title" translate>admin.2fa.available-providers</div>
              @if (!atListOneProvider) {
                <tb-error noMargin error="{{ 'admin.2fa.available-providers-required' | translate }}" class="flex h-4 items-center pl-3"/>
              }
              @for (provider of providersForm.controls; track trackByElement(i, provider); let i = $index) {
                <div class="tb-form-panel stroked tb-slide-toggle">
                  <mat-expansion-panel class="tb-settings" [formGroupName]="i">
                    <mat-expansion-panel-header>
                      <mat-panel-title>
                        <mat-slide-toggle class="mat-slide flex items-center justify-start"
                                          (mousedown)="toggleExtensionPanel($event, i+1, provider.get('enable').value)"
                                          formControlName="enable">
                          {{ twoFactorAuthProvidersData.get(provider.value.providerType).name | translate }}
                        </mat-slide-toggle>
                      </mat-panel-title>
                    </mat-expansion-panel-header>
                    <ng-template matExpansionPanelContent>
                      @switch (provider.get('providerType').value) {
                        @case (twoFactorAuthProviderType.TOTP) {
                          <mat-form-field class="mat-block flex-1" appearance="outline" subscriptSizing="dynamic">
                            <mat-label translate>admin.2fa.issuer-name</mat-label>
                            <input matInput formControlName="issuerName" required>
                            @if (provider.get('issuerName').hasError('required') ||
                              provider.get('issuerName').hasError('pattern')) {
                              <mat-error>
                                {{ "admin.2fa.issuer-name-required" | translate }}
                              </mat-error>
                            }
                          </mat-form-field>
                        }
                        @case (twoFactorAuthProviderType.SMS) {
                          <div
                            >
                            <mat-form-field class="mat-block flex-1" appearance="outline">
                              <mat-label translate>admin.2fa.verification-message-template</mat-label>
                              <input matInput formControlName="smsVerificationMessageTemplate" required>
                              @if (provider.get('smsVerificationMessageTemplate').hasError('required')) {
                                <mat-error>
                                  {{ "admin.2fa.verification-message-template-required" | translate }}
                                </mat-error>
                              }
                              @if (provider.get('smsVerificationMessageTemplate').hasError('pattern')) {
                                <mat-error>
                                  {{ "admin.2fa.verification-message-template-pattern" | translate }}
                                </mat-error>
                              }
                            </mat-form-field>
                            <tb-time-unit-input
                              appearance="outline"
                              subscriptSizing="dynamic"
                              required
                              labelText="{{ 'admin.2fa.verification-code-lifetime' | translate }}"
                              requiredText="{{ 'admin.2fa.verification-code-lifetime-required' | translate }}"
                              minErrorText="{{ 'admin.2fa.verification-code-lifetime-pattern' | translate }}"
                              [minTime]="1"
                              formControlName="verificationCodeLifetime">
                            </tb-time-unit-input>
                          </div>
                        }
                        @case (twoFactorAuthProviderType.EMAIL) {
                          <div>
                            <tb-time-unit-input
                              appearance="outline"
                              subscriptSizing="dynamic"
                              required
                              labelText="{{ 'admin.2fa.verification-code-lifetime' | translate }}"
                              requiredText="{{ 'admin.2fa.verification-code-lifetime-required' | translate }}"
                              minErrorText="{{ 'admin.2fa.verification-code-lifetime-pattern' | translate }}"
                              [minTime]="1"
                              formControlName="verificationCodeLifetime">
                            </tb-time-unit-input>
                          </div>
                        }
                        @case (twoFactorAuthProviderType.BACKUP_CODE) {
                          <div>
                            <mat-form-field class="mat-block flex-1" appearance="outline" subscriptSizing="dynamic">
                              <mat-label translate>admin.2fa.number-of-codes</mat-label>
                              <input matInput formControlName="codesQuantity" type="number" step="1" min="1" required>
                              @if (provider.get('codesQuantity').hasError('required')) {
                                <mat-error>
                                  {{ "admin.2fa.number-of-codes-required" | translate }}
                                </mat-error>
                              }
                              @if (provider.get('codesQuantity').hasError('min') ||
                                provider.get('codesQuantity').hasError('pattern')) {
                                <mat-error>
                                  {{ "admin.2fa.number-of-codes-pattern" | translate }}
                                </mat-error>
                              }
                            </mat-form-field>
                          </div>
                        }
                      }
                    </ng-template>
                  </mat-expansion-panel>
                </div>
              }
            </section>
            <section class="tb-form-panel stroked mb-4">
              <div class="tb-form-panel-title" translate>admin.2fa.verification-limitations</div>
              <div class="tb-form-panel no-gap no-border no-padding">
                <div class="input-row flex flex-col">
                  <tb-time-unit-input
                    appearance="outline"
                    required
                    labelText="{{ 'admin.2fa.total-allowed-time-for-verification' | translate }}"
                    requiredText="{{ 'admin.2fa.total-allowed-time-for-verification-required' | translate }}"
                    minErrorText="{{ 'admin.2fa.total-allowed-time-for-verification-pattern' | translate }}"
                    [minTime]="60"
                    formControlName="totalAllowedTimeForVerification">
                  </tb-time-unit-input>
                  <tb-time-unit-input
                    appearance="outline"
                    required
                    labelText="{{ 'admin.2fa.retry-verification-code-period' | translate }}"
                    requiredText="{{ 'admin.2fa.retry-verification-code-period-required' | translate }}"
                    minErrorText="{{ 'admin.2fa.retry-verification-code-period-pattern' | translate }}"
                    [minTime]="5"
                    formControlName="minVerificationCodeSendPeriod">
                  </tb-time-unit-input>
                  <mat-form-field class="mat-block flex-1" appearance="outline">
                    <mat-label translate>admin.2fa.max-verification-failures-before-user-lockout</mat-label>
                    <input matInput formControlName="maxVerificationFailuresBeforeUserLockout" type="number" step="1" min="0" max="65535">
                    @if (twoFaFormGroup.get('maxVerificationFailuresBeforeUserLockout').hasError('pattern')
                      || twoFaFormGroup.get('maxVerificationFailuresBeforeUserLockout').hasError('min')
                      || twoFaFormGroup.get('maxVerificationFailuresBeforeUserLockout').hasError('max')) {
                      <mat-error>
                        {{ 'admin.2fa.max-verification-failures-before-user-lockout-pattern' | translate }}
                      </mat-error>
                    }
                  </mat-form-field>
                </div>
                <div class="tb-form-panel stroked tb-slide-toggle">
                  <mat-expansion-panel class="tb-settings">
                    <mat-expansion-panel-header>
                      <mat-panel-title>
                        <mat-slide-toggle class="mat-slide flex items-center justify-start" (mousedown)="toggleExtensionPanel($event, providersForm.length+1, twoFaFormGroup.get('verificationCodeCheckRateLimitEnable').value)"
                                          formControlName="verificationCodeCheckRateLimitEnable">
                          {{ 'admin.2fa.verification-code-check-rate-limit' | translate }}
                        </mat-slide-toggle>
                      </mat-panel-title>
                    </mat-expansion-panel-header>
                    <ng-template matExpansionPanelContent>
                      <div class="flex flex-col">
                        <mat-form-field class="mat-block flex-1" appearance="outline">
                          <mat-label translate>admin.2fa.number-of-checking-attempts</mat-label>
                          <input matInput formControlName="verificationCodeCheckRateLimitNumber" required type="number" step="1" min="1">
                          @if (twoFaFormGroup.get('verificationCodeCheckRateLimitNumber').hasError('required')) {
                            <mat-error>
                              {{ 'admin.2fa.number-of-checking-attempts-required' | translate }}
                            </mat-error>
                          }
                          @if (twoFaFormGroup.get('verificationCodeCheckRateLimitNumber').hasError('pattern')
                            || twoFaFormGroup.get('verificationCodeCheckRateLimitNumber').hasError('min')) {
                            <mat-error>
                              {{ 'admin.2fa.number-of-checking-attempts-pattern' | translate }}
                            </mat-error>
                          }
                        </mat-form-field>
                        <tb-time-unit-input
                          appearance="outline"
                          subscriptSizing="dynamic"
                          required
                          labelText="{{ 'admin.2fa.within-time' | translate }}"
                          requiredText="{{ 'admin.2fa.within-time-required' | translate }}"
                          minErrorText="{{ 'admin.2fa.within-time-pattern' | translate }}"
                          [minTime]="1"
                          formControlName="verificationCodeCheckRateLimitTime">
                        </tb-time-unit-input>
                      </div>
                    </ng-template>
                  </mat-expansion-panel>
                </div>
              </div>
            </section>
          </div>
          <div class="flex flex-row items-center justify-end gap-2">
            <button mat-button mat-raised-button color="primary"
                    [disabled]="(isLoading$ | async) || twoFaFormGroup.invalid || !twoFaFormGroup.dirty || !atListOneProvider"
                    type="submit">
              {{'action.save' | translate}}
            </button>
          </div>
        </fieldset>
      </form>
    </mat-card-content>
  </mat-card>
</div>
