import {
  inject,
  provideAppInitializer,
  type EnvironmentProviders,
  type Provider,
} from '@angular/core';
import type { CanActivateFn } from '@angular/router';
import {
  AUTH_GUARD,
  AuthenticationAuroraAdapterService,
  authorizationCodeGuard,
  authenticationPasswordGuard,
  AuthenticationService,
  CurrentAccountService,
  LangService,
  provideApollo,
  provideAuthenticatedInitializer,
  provideAuthentication,
  provideValidationMessages,
  AnonymousCurrentAccountAdapter,
} from '@aurora';
import { environment } from 'environments/environment';
import { AUTH_STRATEGY, type AuthStrategy } from '../environments/environment.type';
/**
 * Returns the correct authentication guard for the given deploy-time strategy.
 *
 * Exported so that unit tests can exercise the REAL selection logic:
 *   - AUTH_STRATEGY.PASSWORD            → authenticationPasswordGuard
 *   - AUTH_STRATEGY.AUTHORIZATION_CODE  → authorizationCodeGuard
 *
 * Inverting this condition or renaming a branch will immediately fail tests
 * that import and call this function.
 */
export const authGuardForStrategy = (strategy: AuthStrategy): CanActivateFn => {
  if (strategy === AUTH_STRATEGY.AUTHORIZATION_CODE) {
    return authorizationCodeGuard;
  }

  return authenticationPasswordGuard;
};

export const provideAurora = (): Array<Provider | EnvironmentProviders> => [
  provideAuthentication(),
  ...provideApollo(),
  { provide: AuthenticationService, useClass: AuthenticationAuroraAdapterService },
  // Load the current account once the session is established (sign-in or already-valid session on
  // load) — see provideAuthenticatedInitializer. The sidebar just reads the resulting signals.
  provideAuthenticatedInitializer(() => inject(CurrentAccountService).load()),
  // AUTH_GUARD is wired from environment.authStrategy via authGuardForStrategy:
  //   AUTH_STRATEGY.PASSWORD            → authenticationPasswordGuard (local login form + Password Grant)
  //   AUTH_STRATEGY.AUTHORIZATION_CODE  → authorizationCodeGuard (delegates to hub, no local form)
  { provide: AUTH_GUARD, useValue: authGuardForStrategy(environment.authStrategy) },
  provideValidationMessages({
    uniqueEmail: { key: 'Validations.UniqueEmail' },
    uniqueUsername: { key: 'Validations.UniqueUsername' },
    matchOther: { key: 'Validations.MatchOther' },
    passwordRule: { key: 'Validations.PasswordRule' },
  }),
  // Non-blocking: kick off lang load at boot. The signal hydrates synchronously
  // from SessionService localStorage; this just refreshes/warms when stale.
  // If the request fails, the app still boots and uses the cached or empty state.
  provideAppInitializer(() => {
    inject(LangService)
      .load()
      .catch((err) => {
        console.error('[LangService] initial load failed, using cached/empty state', err);
      });
  }),
  { provide: CurrentAccountService, useClass: AnonymousCurrentAccountAdapter }
];
