import { ChangeDetectionStrategy, Component, inject, OnDestroy, signal } from '@angular/core'; import { Router, RouterLink } from '@angular/router'; import { injectAuthService } from '@/core/services/auth.service'; import { GameTimerComponent } from '@/features/game/game-timer.component'; import { AnswerResponse, QuestionData } from '@/features/game/game.models'; import { injectGameService } from '@/features/game/game.service'; import { MainLayoutComponent } from '@/shared/layout/main-layout/main-layout.component'; import { ButtonDirective } from '@/shared/ui/button.directive'; type GameState = | 'instructions' | 'pre-game-countdown' | 'playing' | 'question-feedback' | 'game-over'; @Component({ selector: 'app-game', standalone: true, imports: [MainLayoutComponent, ButtonDirective, GameTimerComponent, RouterLink], templateUrl: './game.component.html', styleUrl: './game.component.scss', changeDetection: ChangeDetectionStrategy.OnPush, }) export default class GameComponent implements OnDestroy { private router = inject(Router); private gameService = injectGameService(); private authService = injectAuthService(); user = this.authService.user; gameState = signal('instructions'); currentQuestion = signal(null); selectedAnswerId = signal(null); lastAnswerResponse = signal(null); totalScore = signal(0); questionTimerKey = signal(0); timeout: ReturnType | null = null; ngOnDestroy(): void { if (this.timeout) { clearTimeout(this.timeout); } } async startGame() { this.gameState.set('pre-game-countdown'); } async onStartLightsComplete() { try { const gameData = await this.gameService.startNewGame(); this.currentQuestion.set(gameData.question_data); this.gameState.set('playing'); this.questionTimerKey.set(Date.now()); } catch (error) { console.error('Failed to start game:', error); this.gameState.set('instructions'); } } async selectAnswer(answerId: number) { if (this.gameState() !== 'playing' || this.selectedAnswerId()) return; this.selectedAnswerId.set(answerId); const gameId = this.gameService.gameId(); if (!gameId) return; try { const response = await this.gameService.submitAnswer(gameId, answerId); this.lastAnswerResponse.set(response); this.totalScore.set(response.total_points); this.gameState.set('question-feedback'); if (response.finish) { this.timeout = setTimeout(() => this.gameOver(), 1500); } else { this.timeout = setTimeout(() => this.loadNextQuestion(), 1500); } } catch (error) { console.error('Failed to submit answer:', error); } } async onGameTimeExpired() { const gameId = this.gameService.gameId(); const question = this.currentQuestion(); if (!gameId || !question || this.gameState() !== 'playing') return; try { const response = await this.gameService.submitTimeout(gameId, question.when_timeout); this.lastAnswerResponse.set(response); this.totalScore.set(response.total_points); this.gameState.set('question-feedback'); if (response.finish) { this.timeout = setTimeout(() => this.gameOver(), 1500); } else { this.timeout = setTimeout(() => this.loadNextQuestion(), 1500); } } catch (error) { console.error('Failed to submit timeout:', error); } } private async loadNextQuestion() { const gameId = this.gameService.gameId(); if (!gameId) return; try { const gameData = await this.gameService.getNextQuestion(gameId); this.currentQuestion.set(gameData.question_data); this.selectedAnswerId.set(null); this.lastAnswerResponse.set(null); this.gameState.set('playing'); this.questionTimerKey.set(Date.now()); } catch (error) { console.error('Failed to load next question:', error); } } gameOver() { this.gameState.set('game-over'); this.timeout = setTimeout(() => this.router.navigate(['/app']), 10_000); } restartGame() { this.gameService.resetGame(); this.gameState.set('instructions'); this.currentQuestion.set(null); this.selectedAnswerId.set(null); this.lastAnswerResponse.set(null); this.totalScore.set(0); this.questionTimerKey.set(0); } isCorrectAnswer(answerId: number): boolean { const response = this.lastAnswerResponse(); return response ? response.correct_answer_id === answerId : false; } isSelectedAnswer(answerId: number): boolean { return this.selectedAnswerId() === answerId; } userDisplayName(): string { const user = this.user.data(); if (!user) return '...'; const fullName = (user as { fullname?: unknown }).fullname; if (typeof fullName === 'string' && fullName) return fullName; const name = (user as { name?: unknown }).name; if (typeof name === 'string' && name) return name; return '...'; } // Get letter label for answer (A, B, C, D) getAnswerLabel(index: number): string { return String.fromCharCode(65 + index); // A=65, B=66, C=67, D=68 } }