import { Injectable, inject } from '@angular/core';
import { finalize, forkJoin, Observable, of, shareReplay, tap } from 'rxjs';
import { AppContextState, MenuContext } from '../models/context.model';
import { MenuService } from './menu.service';
import { PermissionService } from './permission.service';
import { TenantContextService } from './tenant-context.service';
import { UserContextService } from './user-context.service';
import { NavService } from '../../shared/services/nav.service';

@Injectable({ providedIn: 'root' })
export class AppContextService {
  private readonly userContextService = inject(UserContextService);
  private readonly tenantContextService = inject(TenantContextService);
  private readonly permissionService = inject(PermissionService);
  private readonly menuService = inject(MenuService);
  private readonly navService = inject(NavService);

  private loadRequest$: Observable<AppContextState> | null = null;
  private menuLoadRequest$: Observable<MenuContext> | null = null;
  private loaded = false;

  ensureMenuInitialized(forceReload = false): Observable<MenuContext> {
    const currentMenu = this.menuService.menuContext();
    if (currentMenu && !forceReload) {
      this.navService.setMenuItems(this.menuService.getNavigationMenu());
      return of(currentMenu);
    }

    if (this.menuLoadRequest$ && !forceReload) {
      return this.menuLoadRequest$;
    }

    this.menuLoadRequest$ = this.menuService.loadMenu().pipe(
      tap(() => {
        this.navService.setMenuItems(this.menuService.getNavigationMenu());
      }),
      finalize(() => {
        this.menuLoadRequest$ = null;
      }),
      shareReplay(1)
    );

    return this.menuLoadRequest$;
  }

  loadAppContext(forceReload = false): Observable<AppContextState> {
    if (this.loaded && !forceReload) {
      return of(this.getCurrentState());
    }

    if (this.loadRequest$ && !forceReload) {
      return this.loadRequest$;
    }

    this.loadRequest$ = forkJoin({
      user: this.userContextService.loadCurrentUserProfile(),
      tenant: this.tenantContextService.loadTenantContext(),
      permissions: this.permissionService.loadPermissions(),
      menu: this.menuService.loadMenu(),
    }).pipe(
      tap((context) => {
        this.navService.setMenuItems(this.menuService.getNavigationMenu());
        this.loaded = true;
      }),
      finalize(() => {
        this.loadRequest$ = null;
      }),
      shareReplay(1)
    );

    return this.loadRequest$;
  }

  ensureContextLoaded(): Observable<AppContextState> {
    return this.loadAppContext();
  }

  clearContext(): void {
    this.userContextService.clear();
    this.tenantContextService.clear();
    this.permissionService.clear();
    this.menuService.clear();
    this.navService.clearMenuItems();
    this.loaded = false;
    this.loadRequest$ = null;
  }

  getDefaultLandingPage(): string {
    return this.userContextService.currentUserContext()?.defaultLandingPage
      ?? this.permissionService.permissionContext()?.defaultLandingPage
      ?? this.tenantContextService.tenantContext()?.defaultLandingPage
      ?? this.menuService.getDefaultLandingPage()
      ?? '/dashboards/crm';
  }

  private getCurrentState(): AppContextState {
    return {
      user: this.userContextService.currentUserContext() ?? { id: '', email: '', roles: [] },
      tenant: this.tenantContextService.tenantContext() ?? {},
      permissions: this.permissionService.permissionContext() ?? { roles: [], permissions: [] },
      menu: this.menuService.menuContext() ?? { items: [] },
    };
  }
}