import { Injectable, DestroyRef, inject } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { interval, startWith, Subscription, switchMap } from 'rxjs';
import { GameApiService } from './game-api.service';
import { GameStreamEvent } from '../models/game.models';

@Injectable({ providedIn: 'root' })
export class GameStreamService {
  private readonly gameApi = inject(GameApiService);
  private readonly destroyRef = inject(DestroyRef);
  private streamSubscription: Subscription | null = null;
  private pollSubscription: Subscription | null = null;
  private lastGameStateHash: string | null = null;

  startStreaming(
    gameId: string,
    onEvent: (event: GameStreamEvent) => void,
    onStreamError: () => void
  ): void {
    this.streamSubscription = this.gameApi
      .streamGame(gameId)
      .pipe(takeUntilDestroyed(this.destroyRef))
      .subscribe({
        next: (event) => {
          this.lastGameStateHash = JSON.stringify(event);
          onEvent(event);
        },
        error: () => {
          onStreamError();
          this.startPolling(gameId, onEvent);
        },
        complete: () => {
          onStreamError();
          this.startPolling(gameId, onEvent);
        }
      });
  }

  startPolling(gameId: string, onEvent: (event: GameStreamEvent) => void): void {
    if (this.pollSubscription) {
      return;
    }

    this.pollSubscription = interval(5000)
      .pipe(
        startWith(0),
        switchMap(() => this.gameApi.getGame(gameId)),
        takeUntilDestroyed(this.destroyRef)
      )
      .subscribe({
        next: (game) => {
          // Only emit if game state changed to avoid unnecessary updates
          const stateHash = JSON.stringify(game.state);
          if (this.lastGameStateHash !== stateHash) {
            this.lastGameStateHash = stateHash;
            const event: GameStreamEvent = {
              type: 'gameFull',
              game
            };
            onEvent(event);
          }
        }
      });
  }

  cleanup(): void {
    this.streamSubscription?.unsubscribe();
    this.pollSubscription?.unsubscribe();
    this.streamSubscription = null;
    this.pollSubscription = null;
    this.lastGameStateHash = null;
  }
}
