import { Injectable, inject, signal } from '@angular/core';
import { Observable, of, throwError } from 'rxjs';
import { catchError, map, shareReplay, tap } from 'rxjs/operators';
import { BootstrapConfig, DEFAULT_BOOTSTRAP } from '../../shared/models/config';
import { CONFIG_PROVIDER } from './config-provider.token';

@Injectable({ providedIn: 'root' })
export class ConfigService {
  private readonly provider = inject(CONFIG_PROVIDER);

  private bootstrapSnapshot: BootstrapConfig | null = null;
  private bootstrap$?: Observable<BootstrapConfig>;
  private readonly revisionState = signal(0);

  readonly bootstrapRevision = this.revisionState.asReadonly();

  loadBootstrap(forceRefresh: boolean = false): Observable<BootstrapConfig> {
    if (this.bootstrapSnapshot && !forceRefresh && this.bootstrap$) {
      return this.bootstrap$;
    }

    if (!this.bootstrap$ || forceRefresh) {
      this.bootstrap$ = this.provider.loadBootstrap().pipe(
        map(config => (config.published === false ? DEFAULT_BOOTSTRAP : config)),
        tap(config => {
          this.bootstrapSnapshot = config;
          this.revisionState.update(value => value + 1);
        }),
        shareReplay(1),
        catchError(error => {
          this.bootstrap$ = undefined;
          this.bootstrapSnapshot = null;
          return throwError(() => error);
        })
      );
    }

    return this.bootstrap$;
  }

  getBootstrapSnapshot(): BootstrapConfig | null {
    return this.bootstrapSnapshot;
  }

  applyBootstrapOverride(next: BootstrapConfig): void {
    const cloned = JSON.parse(JSON.stringify(next)) as BootstrapConfig;
    this.bootstrapSnapshot = cloned;
    this.bootstrap$ = of(cloned);
    this.revisionState.update(value => value + 1);
  }
}
