import { Injectable, DestroyRef, inject } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { delay, Subscription } from 'rxjs';
import { GameApiService } from './game-api.service';
import { getErrorMessage } from '../core/http/error-message.util';
import { GameFull, GameState } from '../models/game.models';

@Injectable({ providedIn: 'root' })
export class BotMoveService {
  private readonly gameApi = inject(GameApiService);
  private readonly destroyRef = inject(DestroyRef);
  private botMoveSubscription: Subscription | null = null;

  private isBotPlayer(playerId: string): boolean {
    return playerId.startsWith('bot-');
  }

  isPlayingAgainstBot(game: GameFull | null): boolean {
    if (!game) {
      return false;
    }
    return this.isBotPlayer(game.white.id) || this.isBotPlayer(game.black.id);
  }

  isCurrentPlayerBot(game: GameFull | null, state: GameState | null): boolean {
    if (!game || !state) {
      return false;
    }
    const currentPlayer = state.turn === 'white' ? game.white : game.black;
    return this.isBotPlayer(currentPlayer.id);
  }

  tryMakeBotMove(
    gameId: string,
    game: GameFull | null,
    state: GameState | null,
    onSuccess: (updatedState: GameState) => void,
    onError: (error: string) => void
  ): void {
    if (!this.isPlayingAgainstBot(game) || !this.isCurrentPlayerBot(game, state) || !state) {
      return;
    }

    this.botMoveSubscription?.unsubscribe();
    this.botMoveSubscription = this.gameApi
      .getLegalMoves(gameId)
      .pipe(
        delay(1000),
        takeUntilDestroyed(this.destroyRef)
      )
      .subscribe({
        next: (response) => {
          if (response.moves.length === 0) {
            return;
          }
          const botMove = response.moves[Math.floor(Math.random() * response.moves.length)];
          this.gameApi
            .makeMove(gameId, botMove.uci)
            .pipe(takeUntilDestroyed(this.destroyRef))
            .subscribe({
              next: (updatedState) => {
                onSuccess(updatedState);
              },
              error: (error) => {
                onError(getErrorMessage(error, 'Bot move failed.'));
              }
            });
        },
        error: () => {
          onError('Could not get legal moves for bot move.');
        }
      });
  }

  cleanup(): void {
    this.botMoveSubscription?.unsubscribe();
  }
}
