import { Component, OnDestroy, OnInit } from "@angular/core";
import { ActivatedRoute } from "@angular/router";
import {
  combineLatestWith,
  firstValueFrom,
  Observable,
  startWith,
  Subject,
  switchMap,
  takeUntil,
} from "rxjs";

import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { DialogService } from "@bitwarden/components";
import { openUserVerificationPrompt } from "@bitwarden/web-vault/app/auth/shared/components/user-verification";

import { ServiceAccountView } from "../../models/view/service-account.view";
import { AccessTokenView } from "../models/view/access-token.view";
import { ServiceAccountService } from "../service-account.service";

import { AccessService } from "./access.service";
import { AccessTokenCreateDialogComponent } from "./dialogs/access-token-create-dialog.component";

@Component({
  selector: "sm-access-tokens",
  templateUrl: "./access-tokens.component.html",
})
export class AccessTokenComponent implements OnInit, OnDestroy {
  accessTokens$: Observable<AccessTokenView[]>;

  private destroy$ = new Subject<void>();
  private serviceAccountView: ServiceAccountView;

  constructor(
    private route: ActivatedRoute,
    private accessService: AccessService,
    private dialogService: DialogService,
    private platformUtilsService: PlatformUtilsService,
    private i18nService: I18nService,
    private serviceAccountService: ServiceAccountService,
  ) {}

  ngOnInit() {
    this.accessTokens$ = this.accessService.accessToken$.pipe(
      startWith(null),
      combineLatestWith(this.route.params),
      switchMap(async ([_, params]) =>
        this.accessService.getAccessTokens(params.organizationId, params.serviceAccountId),
      ),
    );

    this.serviceAccountService.serviceAccount$
      .pipe(
        startWith(null),
        combineLatestWith(this.route.params),
        switchMap(([_, params]) =>
          this.serviceAccountService.getByServiceAccountId(
            params.serviceAccountId,
            params.organizationId,
          ),
        ),
        takeUntil(this.destroy$),
      )
      .subscribe((serviceAccountView) => {
        this.serviceAccountView = serviceAccountView;
      });
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }

  protected async revoke(tokens: AccessTokenView[]) {
    if (!tokens?.length) {
      this.platformUtilsService.showToast(
        "error",
        null,
        this.i18nService.t("noAccessTokenSelected"),
      );
      return;
    }

    if (!(await this.verifyUser())) {
      return;
    }

    await this.accessService.revokeAccessTokens(
      this.serviceAccountView.id,
      tokens.map((t) => t.id),
    );

    this.platformUtilsService.showToast("success", null, this.i18nService.t("accessTokenRevoked"));
  }

  protected openNewAccessTokenDialog() {
    AccessTokenCreateDialogComponent.openNewAccessTokenDialog(
      this.dialogService,
      this.serviceAccountView,
    );
  }

  private verifyUser() {
    const ref = openUserVerificationPrompt(this.dialogService, {
      data: {
        confirmDescription: "revokeAccessTokenDesc",
        confirmButtonText: "revokeAccessToken",
        modalTitle: "revokeAccessToken",
      },
    });

    if (ref == null) {
      return;
    }

    return firstValueFrom(ref.closed);
  }
}
