import { Component, DestroyRef, HostListener, OnInit, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Router } from '@angular/router';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { AuthService } from '../../services/auth.service';
import { AuthDialogService } from '../../services/auth-dialog.service';
import { CurrentUser } from '../../models/auth.models';
import { LoginDialogComponent } from '../login-dialog/login-dialog.component';
import { RegisterDialogComponent } from '../register-dialog/register-dialog.component';
import { ThemeService } from '../../services/theme.service';
import { ChallengeEventService } from '../../services/challenge-event.service';
import { ChallengeService } from '../../services/challenge.service';
import { ChallengeWebSocketService } from '../../services/challenge-websocket.service';
import { Challenge } from '../../models/challenge.models';

@Component({
  selector: 'app-toolbar',
  standalone: true,
  imports: [CommonModule, LoginDialogComponent, RegisterDialogComponent],
  templateUrl: './toolbar.component.html',
  styleUrl: './toolbar.component.css'
})
export class ToolbarComponent implements OnInit {
  private readonly destroyRef = inject(DestroyRef);
  private readonly authService = inject(AuthService);
  private readonly authDialogService = inject(AuthDialogService);
  private readonly themeService = inject(ThemeService);
  private readonly challengeEventService = inject(ChallengeEventService);
  private readonly challengeService = inject(ChallengeService);
  private readonly challengeWs = inject(ChallengeWebSocketService);
  private readonly router = inject(Router);

  private pollHandle: ReturnType<typeof setInterval> | null = null;
  private readonly navigatedChallengeIds = new Set<string>();

  currentUser: CurrentUser | null = null;
  showLoginDialog = false;
  showRegisterDialog = false;
  isDarkMode = false;
  profileOpen = false;
  notifOpen = false;
  incomingChallenges: Challenge[] = [];
  acceptingId: string | null = null;
  decliningId: string | null = null;

  ngOnInit(): void {
    this.destroyRef.onDestroy(() => this.stopPolling());

    this.authService.currentUser$
      .pipe(takeUntilDestroyed(this.destroyRef))
      .subscribe(user => {
        this.currentUser = user;
        if (user) {
          this.challengeWs.connect();
          this.startPolling();
        } else {
          this.challengeWs.disconnect();
          this.stopPolling();
          this.navigatedChallengeIds.clear();
          this.challengeEventService.clear();
        }
      });

    this.authDialogService.dialogState$
      .pipe(takeUntilDestroyed(this.destroyRef))
      .subscribe(state => {
        this.showLoginDialog = state === 'login';
        this.showRegisterDialog = state === 'register';
      });

    this.themeService.darkMode$
      .pipe(takeUntilDestroyed(this.destroyRef))
      .subscribe(isDark => { this.isDarkMode = isDark; });

    this.challengeEventService.getIncomingChallenges$()
      .pipe(takeUntilDestroyed(this.destroyRef))
      .subscribe(challenges => { this.incomingChallenges = challenges; });
  }

  private startPolling(): void {
    this.fetchChallenges();
    this.pollHandle = setInterval(() => this.fetchChallenges(), 10_000);
  }

  private stopPolling(): void {
    if (this.pollHandle !== null) {
      clearInterval(this.pollHandle);
      this.pollHandle = null;
    }
  }

  private fetchChallenges(): void {
    this.challengeService.listChallenges().subscribe({
      next: response => {
        const incoming = response.in ?? response.incoming ?? [];
        this.challengeEventService.setIncomingChallenges(incoming);

        const outgoing = response.out ?? response.outgoing ?? [];
        for (const c of outgoing) {
          if (c.status === 'accepted' && c.gameId && !this.navigatedChallengeIds.has(c.id)) {
            this.navigatedChallengeIds.add(c.id);
            if (!this.router.url.includes(`/game/${c.gameId}`)) {
              void this.router.navigate(['/game', c.gameId]);
            }
          }
        }
      }
    });
  }

  @HostListener('document:click', ['$event'])
  onDocumentClick(event: MouseEvent): void {
    if (!(event.target as HTMLElement).closest('[data-dropdown]')) {
      this.profileOpen = false;
      this.notifOpen = false;
    }
  }

  toggleProfile(event: MouseEvent): void {
    event.stopPropagation();
    const wasOpen = this.profileOpen;
    this.profileOpen = false;
    this.notifOpen = false;
    this.profileOpen = !wasOpen;
  }

  toggleNotif(event: MouseEvent): void {
    event.stopPropagation();
    const wasOpen = this.notifOpen;
    this.profileOpen = false;
    this.notifOpen = false;
    this.notifOpen = !wasOpen;
  }

  openLoginDialog(): void {
    this.profileOpen = false;
    this.notifOpen = false;
    this.authDialogService.openLogin();
  }

  closeLoginDialog(): void {
    this.authDialogService.close();
  }

  openRegisterDialog(): void {
    this.profileOpen = false;
    this.notifOpen = false;
    this.authDialogService.openRegister();
  }

  closeRegisterDialog(): void {
    this.authDialogService.close();
  }

  logout(): void {
    this.profileOpen = false;
    this.notifOpen = false;
    this.authService.logout();
  }

  toggleTheme(event: MouseEvent): void {
    event.stopPropagation();
    this.themeService.toggleTheme();
  }

  goToHome(): void {
    void this.router.navigate(['/']);
  }

  goToProfile(): void {
    this.profileOpen = false;
    this.notifOpen = false;
    void this.router.navigate(['/profile']);
  }

  goToGames(): void {
    this.profileOpen = false;
    this.notifOpen = false;
    void this.router.navigate(['/games']);
  }

  goToTournaments(): void {
    this.profileOpen = false;
    this.notifOpen = false;
    void this.router.navigate(['/tournaments']);
  }

  goToChallenges(): void {
    this.profileOpen = false;
    this.notifOpen = false;
    void this.router.navigate(['/challenges']);
  }

  goToBots(): void {
    this.profileOpen = false;
    this.notifOpen = false;
    void this.router.navigate(['/bots']);
  }

  goToAnalysis(): void {
    this.profileOpen = false;
    this.notifOpen = false;
    void this.router.navigate(['/analysis']);
  }

  onLoginSuccess(): void {
    this.closeLoginDialog();
  }

  onRegisterSuccess(): void {
    this.closeRegisterDialog();
  }

  getInitial(): string {
    return this.currentUser?.username?.charAt(0).toUpperCase() ?? '?';
  }

  getTimeControlDisplay(challenge: Challenge): string {
    const { limit, increment } = challenge.timeControl;
    if (!limit || !increment) return 'Unlimited';
    return `${Math.floor(limit / 60)}+${increment}`;
  }

  getExpirationInfo(challenge: Challenge): string {
    const diff = new Date(challenge.expiresAt).getTime() - Date.now();
    if (diff <= 0) return 'Expired';
    const min = Math.floor(diff / 60000);
    return min > 60 ? `${Math.floor(min / 60)}h` : `${min}m`;
  }

  acceptChallenge(event: MouseEvent, challenge: Challenge): void {
    event.stopPropagation();
    if (this.acceptingId || this.decliningId) return;
    this.acceptingId = challenge.id;
    this.challengeService.acceptChallenge(challenge.id).subscribe({
      next: accepted => {
        this.acceptingId = null;
        this.challengeEventService.onChallengeAccepted(accepted);
        if (accepted.gameId) void this.router.navigate(['/game', accepted.gameId]);
      },
      error: () => { this.acceptingId = null; }
    });
  }

  declineChallenge(event: MouseEvent, challenge: Challenge): void {
    event.stopPropagation();
    if (this.acceptingId || this.decliningId) return;
    this.decliningId = challenge.id;
    this.challengeService.declineChallenge(challenge.id, { reason: 'generic' }).subscribe({
      next: () => {
        this.decliningId = null;
        this.challengeEventService.removeChallenge(challenge.id);
      },
      error: () => { this.decliningId = null; }
    });
  }
}
