import { Injectable, OnDestroy, inject, signal } from '@angular/core';
import { MsalBroadcastService, MsalService } from '@azure/msal-angular';
import { AccountInfo, InteractionStatus } from '@azure/msal-browser';
import {
  BehaviorSubject,
  Subscription,
  filter,
  map,
  shareReplay,
  tap,
} from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class AuthService implements OnDestroy {
  private subscriptions = new Subscription();
  private account$ = new BehaviorSubject<AccountInfo | undefined>(undefined);

  activeAccount$ = this.account$.pipe(
    tap((account) =>
      this.msalService.instance.setActiveAccount(account ?? null)
    ),
    tap((account) => this.activeAccount.set(account))
  );
  activeAccount = signal<AccountInfo | undefined>(undefined);
  roles$ = this.activeAccount$.pipe(
    filter(Boolean),
    map((account) => account?.idTokenClaims?.roles),
    shareReplay(1)
  );

  msalService = inject(MsalService);
  msalBroadcastService = inject(MsalBroadcastService);

  constructor() {
    this.subscriptions.add(
      this.msalBroadcastService.inProgress$
        .pipe(
          filter((status) => status === InteractionStatus.None),
          tap(() => this.setActiveAccount())
        )
        .subscribe()
    );
  }

  ngOnDestroy(): void {
    this.subscriptions.unsubscribe();
  }

  logout(): void {
    this.msalService.logoutRedirect();
  }

  private setActiveAccount(): void {
    const activeAccount = this.msalService.instance.getActiveAccount();

    if (
      !activeAccount &&
      this.msalService.instance.getAllAccounts().length > 0
    ) {
      const accounts = this.msalService.instance.getAllAccounts();
      this.account$.next(accounts.at(0));
    } else if (activeAccount) {
      this.account$.next(activeAccount);
    }
  }
}
