import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, HostListener, computed, inject, signal, viewChild } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ActivatedRoute, NavigationEnd, Router, RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router';
import { filter } from 'rxjs/operators';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { TranslatePipe } from '../../../i18n/translate.pipe';
import { TranslateService } from '../../../i18n/translate.service';
import { LanguageService } from '../../../services/language.service';
import { AdminAuthService } from '@marketplaces/auth';
import { ADMIN_NAV_BOTTOM, ADMIN_NAV_PRIMARY, AdminBreadcrumbEntry, AdminNavEntry } from './admin-nav.model';
import { IconComponent } from '../../../shared/ui/icon/icon.component';
import { AdminPreferencesService } from '../settings/services/admin-preferences.service';
import { UiRuntimeFacade } from '../../../facades/runtime/ui-runtime.facade';
import { ConfigService } from '../../../core/config/config.service';
import { AdminOrderWatcherService } from './services/admin-order-watcher.service';

@Component({
  selector: 'app-admin-layout',
  standalone: true,
  imports: [CommonModule, RouterOutlet, RouterLink, RouterLinkActive, TranslatePipe, IconComponent],
  templateUrl: './admin-layout.component.html',
  styleUrl: './admin-layout.component.scss',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AdminLayoutComponent {
  private readonly router = inject(Router);
  private readonly route = inject(ActivatedRoute);
  private readonly destroyRef = inject(DestroyRef);
  private readonly translate = inject(TranslateService);
  private readonly languageService = inject(LanguageService);
  private readonly adminAuth = inject(AdminAuthService);
  private readonly preferences = inject(AdminPreferencesService);
  private readonly uiRuntime = inject(UiRuntimeFacade);
  private readonly configService = inject(ConfigService);
  private readonly orderWatcher = inject(AdminOrderWatcherService);

  readonly unreadCount = this.orderWatcher.unreadCount;
  readonly recentOrders = this.orderWatcher.recentOrders;

  readonly density = this.preferences.density;

  private readonly drawerEl = viewChild<ElementRef<HTMLElement>>('drawer');
  private readonly menuToggleEl = viewChild<ElementRef<HTMLElement>>('menuToggle');

  readonly navPrimary: AdminNavEntry[] = ADMIN_NAV_PRIMARY;

  readonly navBottom = computed<AdminNavEntry[]>(() => {
    this.configService.bootstrapRevision();
    const supportEmail = this.uiRuntime.contactEmail();
    const documentationUrl = this.configService.getBootstrapSnapshot()?.tenant?.documentationUrl;

    return ADMIN_NAV_BOTTOM.map(entry => {
      if (entry.type !== 'link') {
        return entry;
      }
      if (entry.id === 'help' && supportEmail) {
        return { ...entry, comingSoon: false, externalHref: `mailto:${supportEmail}` };
      }
      if (entry.id === 'documentation' && documentationUrl) {
        return { ...entry, comingSoon: false, externalHref: documentationUrl };
      }
      return entry;
    });
  });

  readonly mobileDrawerOpen = signal(false);
  readonly notificationsOpen = signal(false);

  readonly currentLang = this.languageService.currentLanguage;
  readonly displayName = this.adminAuth.displayName;

  readonly initials = computed(() => {
    const name = this.displayName();
    if (!name) {
      return '?';
    }
    return name
      .split(/\s+/)
      .filter(Boolean)
      .slice(0, 2)
      .map(part => part[0]?.toUpperCase())
      .join('');
  });

  private readonly breadcrumbSignal = signal<AdminBreadcrumbEntry[]>([]);
  private readonly titleKeySignal = signal<string>('adminShell.pages.dashboard.title');
  private readonly descriptionKeySignal = signal<string>('adminShell.pages.dashboard.description');

  readonly breadcrumb = this.breadcrumbSignal.asReadonly();
  readonly pageTitleKey = this.titleKeySignal.asReadonly();
  readonly pageDescriptionKey = this.descriptionKeySignal.asReadonly();

  constructor() {
    this.readRouteData();
    this.orderWatcher.start();
    this.destroyRef.onDestroy(() => this.orderWatcher.stop());
    this.router.events
      .pipe(
        filter(event => event instanceof NavigationEnd),
        takeUntilDestroyed(this.destroyRef),
      )
      .subscribe(() => {
        this.readRouteData();
        this.closeMobileDrawer();
        this.notificationsOpen.set(false);
      });
  }

  @HostListener('document:keydown.escape')
  onEscape(): void {
    if (this.mobileDrawerOpen()) {
      this.closeMobileDrawer();
      return;
    }
    if (this.notificationsOpen()) {
      this.notificationsOpen.set(false);
    }
  }

  toggleMobileDrawer(): void {
    this.mobileDrawerOpen.update(open => !open);
    if (this.mobileDrawerOpen()) {
      queueMicrotask(() => {
        const drawer = this.drawerEl()?.nativeElement;
        drawer?.querySelector<HTMLElement>('a, button')?.focus();
      });
    }
  }

  closeMobileDrawer(): void {
    if (!this.mobileDrawerOpen()) {
      return;
    }
    this.mobileDrawerOpen.set(false);
    this.menuToggleEl()?.nativeElement.focus();
  }

  toggleNotifications(): void {
    this.notificationsOpen.update(open => !open);
    if (this.notificationsOpen()) {
      this.orderWatcher.markAllSeen();
    }
  }

  adminLinkFor(entry: Extract<AdminNavEntry, { type: 'link' }>): string[] {
    const lang = this.currentLang();
    if (entry.absolutePath) {
      return ['/', lang, ...entry.absolutePath];
    }
    return ['/', lang, 'backoffice', ...(entry.path ?? [])];
  }

  goToOrder(orderId: string): void {
    void this.router.navigate([this.currentLang(), 'backoffice', 'orders', orderId]);
    this.notificationsOpen.set(false);
  }

  breadcrumbLink(entry: AdminBreadcrumbEntry): string[] {
    return ['/', this.currentLang(), 'backoffice', ...(entry.path ?? [])];
  }

  logout(): void {
    this.adminAuth.logout();
  }

  cardTitle(key: string): string {
    return this.translate.t(key);
  }

  private readRouteData(): void {
    let leaf = this.route;
    while (leaf.firstChild) {
      leaf = leaf.firstChild;
    }
    // Route metadata is optional: during the initial navigation (or for routes
    // registered without `data`) the leaf snapshot may not exist yet. Fall back
    // to dashboard defaults instead of crashing the whole admin shell.
    const data = (leaf.snapshot?.data ?? {}) as {
      titleKey?: string;
      descriptionKey?: string;
      breadcrumb?: AdminBreadcrumbEntry[];
    };
    this.titleKeySignal.set(data.titleKey ?? 'adminShell.pages.dashboard.title');
    this.descriptionKeySignal.set(data.descriptionKey ?? 'adminShell.pages.dashboard.description');
    this.breadcrumbSignal.set(data.breadcrumb ?? []);
  }
}
