import { Component, DestroyRef, OnInit, inject } from '@angular/core';
import { Router, RouterLink } from '@angular/router';
import { forkJoin, of } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { AuthService } from '../../services/auth.service';
import { GameApiService } from '../../services/game-api.service';
import { GameHistoryService } from '../../services/game-history.service';
import { GameFull, GameStatus } from '../../models/game.models';

type GamesTab = 'active' | 'history';

const FINISHED_STATUSES: GameStatus[] = [
  'checkmate', 'stalemate', 'resign', 'draw', 'insufficientMaterial'
];

@Component({
  selector: 'app-games',
  standalone: true,
  imports: [RouterLink],
  templateUrl: './games.component.html',
  styleUrl: './games.component.css'
})
export class GamesComponent implements OnInit {
  private readonly destroyRef = inject(DestroyRef);
  private readonly router = inject(Router);
  private readonly authService = inject(AuthService);
  private readonly gameApi = inject(GameApiService);
  private readonly gameHistory = inject(GameHistoryService);

  tab: GamesTab = 'active';
  loading = true;
  activeGames: GameFull[] = [];
  finishedGames: GameFull[] = [];

  ngOnInit(): void {
    this.authService.currentUser$
      .pipe(takeUntilDestroyed(this.destroyRef))
      .subscribe((user) => {
        if (!user) void this.router.navigate(['/']);
      });

    this.loadGames();
  }

  setTab(tab: GamesTab): void {
    this.tab = tab;
  }

  resumeGame(gameId: string): void {
    void this.router.navigate(['/game', gameId]);
  }

  removeGame(gameId: string): void {
    this.gameHistory.removeGame(gameId);
    this.activeGames = this.activeGames.filter((g) => g.gameId !== gameId);
    this.finishedGames = this.finishedGames.filter((g) => g.gameId !== gameId);
  }

  statusLabel(status: GameStatus): string {
    const labels: Record<GameStatus, string> = {
      started: 'In Progress',
      check: 'Check',
      checkmate: 'Checkmate',
      stalemate: 'Stalemate',
      resign: 'Resigned',
      draw: 'Draw',
      drawOffered: 'Draw Offered',
      fiftyMoveAvailable: 'In Progress',
      promotionPending: 'In Progress',
      insufficientMaterial: 'Draw'
    };
    return labels[status] ?? status;
  }

  isFinished(status: GameStatus): boolean {
    return FINISHED_STATUSES.includes(status);
  }

  private loadGames(): void {
    const ids = this.gameHistory.getGameIds();
    if (ids.length === 0) {
      this.loading = false;
      return;
    }

    const requests = ids.map((id) =>
      this.gameApi.getGame(id).pipe(
        catchError((err: unknown) => {
          if (typeof err === 'object' && err !== null && (err as { status: number }).status === 404) {
            this.gameHistory.removeGame(id);
          }
          return of(null);
        })
      )
    );

    forkJoin(requests)
      .pipe(takeUntilDestroyed(this.destroyRef))
      .subscribe((results) => {
        const valid = results.filter((g): g is GameFull => g !== null);
        this.activeGames = valid.filter((g) => !FINISHED_STATUSES.includes(g.state.status));
        this.finishedGames = valid.filter((g) => FINISHED_STATUSES.includes(g.state.status));
        this.loading = false;
      });
  }
}
