import { Component, inject, OnInit, OnDestroy, DestroyRef } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Router } from '@angular/router';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { ChallengeService } from '../../services/challenge.service';
import { ChallengeEventService } from '../../services/challenge-event.service';
import { Challenge } from '../../models/challenge.models';
import { getErrorMessage } from '../../core/http/error-message.util';

@Component({
    selector: 'app-challenges',
    standalone: true,
    imports: [CommonModule],
    templateUrl: './challenges.component.html',
    styleUrls: ['./challenges.component.css']
})
export class ChallengesComponent implements OnInit, OnDestroy {
    private readonly challengeService = inject(ChallengeService);
    private readonly challengeEventService = inject(ChallengeEventService);
    private readonly router = inject(Router);
    private readonly destroyRef = inject(DestroyRef);

    incomingChallenges: Challenge[] = [];
    outgoingChallenges: Challenge[] = [];
    loading = false;
    errorMessage = '';

    private pollInterval: any = null;
    private readonly pollIntervalMs = 5000; // Poll every 5 seconds

    ngOnInit(): void {
        this.loadChallenges(true);

        // Subscribe to challenge events
        this.challengeEventService.getChallengeReceived$()
            .pipe(takeUntilDestroyed(this.destroyRef))
            .subscribe(() => {
                this.loadChallenges();
            });

        // Start polling for challenge updates
        this.startPolling();
    }

    ngOnDestroy(): void {
        this.stopPolling();
    }

    private startPolling(): void {
        this.pollInterval = setInterval(() => {
            this.loadChallenges(false);
        }, this.pollIntervalMs);
    }

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

    loadChallenges(showLoader = false): void {
        if (showLoader) {
            this.loading = true;
            this.errorMessage = '';
        }

        this.challengeService.listChallenges()
            .pipe(takeUntilDestroyed(this.destroyRef))
            .subscribe({
                next: (response) => {
                    this.incomingChallenges = response.in || response.incoming || [];
                    this.outgoingChallenges = response.out || response.outgoing || [];
                    if (showLoader) {
                        this.loading = false;
                    }
                },
                error: (error) => {
                    this.errorMessage = getErrorMessage(error, 'Failed to load challenges');
                    if (showLoader) {
                        this.loading = false;
                    }
                }
            });
    }

    acceptChallenge(challenge: Challenge): void {
        this.challengeService.acceptChallenge(challenge.id)
            .pipe(takeUntilDestroyed(this.destroyRef))
            .subscribe({
                next: (acceptedChallenge) => {
                    this.challengeEventService.onChallengeAccepted(acceptedChallenge);
                    this.loadChallenges();
                    if (acceptedChallenge.gameId) {
                        void this.router.navigate(['/game', acceptedChallenge.gameId]);
                    } else {
                        this.errorMessage = 'Challenge accepted, but no game was created.';
                    }
                },
                error: (error) => {
                    this.errorMessage = getErrorMessage(error, 'Failed to accept challenge');
                }
            });
    }

    declineChallenge(challenge: Challenge): void {
        this.challengeService.declineChallenge(challenge.id, { reason: 'generic' })
            .pipe(takeUntilDestroyed(this.destroyRef))
            .subscribe({
                next: () => {
                    this.challengeEventService.removeChallenge(challenge.id);
                    this.loadChallenges();
                },
                error: (error) => {
                    this.errorMessage = getErrorMessage(error, 'Failed to decline challenge');
                }
            });
    }

    cancelChallenge(challenge: Challenge): void {
        this.challengeService.cancelChallenge(challenge.id)
            .pipe(takeUntilDestroyed(this.destroyRef))
            .subscribe({
                next: () => {
                    this.loadChallenges();
                },
                error: (error) => {
                    this.errorMessage = getErrorMessage(error, 'Failed to cancel challenge');
                }
            });
    }

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

    openGame(challenge: Challenge): void {
        if (!challenge.gameId) {
            this.errorMessage = 'Missing game id for this challenge.';
            return;
        }
        void this.router.navigate(['/game', challenge.gameId]);
    }

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

    getChallengerDisplay(challenge: Challenge): string {
        return challenge.challenger.name;
    }

    getOpponentDisplay(challenge: Challenge): string {
        return challenge.destUser.name;
    }

    getExpirationInfo(challenge: Challenge): string {
        const expiresAt = new Date(challenge.expiresAt);
        const now = new Date();
        const diffMs = expiresAt.getTime() - now.getTime();

        if (diffMs <= 0 || challenge.status === 'expired') {
            return 'Expired';
        }

        const minutes = Math.floor(diffMs / 60000);
        if (minutes > 60) {
            const hours = Math.floor(minutes / 60);
            return `${hours}h`;
        }

        return `${minutes}m`;
    }
}
