import { Component, inject, OnInit, OnDestroy, DestroyRef, Output, EventEmitter } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule, FormBuilder, FormGroup, Validators } from '@angular/forms';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { finalize } from 'rxjs';
import { ChallengeService } from '../../services/challenge.service';
import { Router } from '@angular/router';
import { getErrorMessage } from '../../core/http/error-message.util';
import { PlayerColor } from '../../models/challenge.models';

type TimeMode = 'blitz' | 'rapid' | 'classical' | 'unlimited';

interface TimePreset {
    label: string;
    limitSeconds: number;
    incrementSeconds: number;
}

@Component({
    selector: 'app-challenge-create-dialog',
    standalone: true,
    imports: [CommonModule, FormsModule, ReactiveFormsModule],
    templateUrl: './challenge-create-dialog.component.html',
    styleUrls: ['./challenge-create-dialog.component.css']
})
export class ChallengeCreateDialogComponent implements OnInit, OnDestroy {
    private readonly challengeService = inject(ChallengeService);
    private readonly router = inject(Router);
    private readonly fb = inject(FormBuilder);
    private readonly destroyRef = inject(DestroyRef);

    @Output() closeChallengeDialog = new EventEmitter<void>();

    form!: FormGroup;
    loading = false;
    errorMessage = '';
    selectedTimeMode: TimeMode = 'rapid';

    timePresets: Record<TimeMode, TimePreset[]> = {
        blitz: [
            { label: '1+0', limitSeconds: 60, incrementSeconds: 0 },
            { label: '2+1', limitSeconds: 120, incrementSeconds: 1 },
            { label: '3+0', limitSeconds: 180, incrementSeconds: 0 },
            { label: '3+2', limitSeconds: 180, incrementSeconds: 2 },
            { label: '5+0', limitSeconds: 300, incrementSeconds: 0 }
        ],
        rapid: [
            { label: '10+0', limitSeconds: 600, incrementSeconds: 0 },
            { label: '10+5', limitSeconds: 600, incrementSeconds: 5 },
            { label: '15+10', limitSeconds: 900, incrementSeconds: 10 },
            { label: '25+10', limitSeconds: 1500, incrementSeconds: 10 }
        ],
        classical: [
            { label: '30+0', limitSeconds: 1800, incrementSeconds: 0 },
            { label: '30+20', limitSeconds: 1800, incrementSeconds: 20 },
            { label: '60+30', limitSeconds: 3600, incrementSeconds: 30 },
            { label: '90+30', limitSeconds: 5400, incrementSeconds: 30 }
        ],
        unlimited: []
    };

    ttlOptions = [
        { label: '5 minutes', seconds: 300 },
        { label: '1 hour', seconds: 3600 },
        { label: '1 day', seconds: 86400 },
        { label: 'No expiry', seconds: 0 }
    ];

    ngOnInit(): void {
        this.initializeForm();
    }

    ngOnDestroy(): void {
    }

    private initializeForm(): void {
        this.form = this.fb.group({
            targetUsername: ['', [Validators.required, Validators.minLength(1)]],
            color: ['random', Validators.required],
            timeMode: ['rapid'],
            limitMinutes: [10, [Validators.required, Validators.min(1), Validators.max(1000)]],
            incrementSeconds: [5, [Validators.required, Validators.min(0), Validators.max(300)]],
            ttlSeconds: [3600, Validators.required]
        });

        this.form.get('timeMode')?.valueChanges
            .pipe(takeUntilDestroyed(this.destroyRef))
            .subscribe((mode: unknown) => {
                const timeMode = mode as TimeMode;
                this.selectedTimeMode = timeMode;
                if (timeMode !== 'unlimited') {
                    const firstPreset = this.timePresets[timeMode][0];
                    if (firstPreset) {
                        this.form.patchValue({
                            limitMinutes: firstPreset.limitSeconds / 60,
                            incrementSeconds: firstPreset.incrementSeconds
                        });
                    }
                }
            });
    }

    selectPreset(preset: TimePreset): void {
        this.form.patchValue({
            limitMinutes: preset.limitSeconds / 60,
            incrementSeconds: preset.incrementSeconds
        });
    }

    getAvailablePresets(): TimePreset[] {
        return this.timePresets[this.selectedTimeMode] || [];
    }

    submit(): void {
        if (this.form.invalid || this.loading) {
            return;
        }

        const targetUsername = this.form.get('targetUsername')?.value?.trim();
        if (!targetUsername) {
            this.errorMessage = 'Please enter a valid username';
            return;
        }

        this.errorMessage = '';
        this.loading = true;
        this.form.disable();

        const limitSeconds = Math.round((this.form.getRawValue().limitMinutes || 0) * 60);
        const { incrementSeconds, ttlSeconds, color: rawColor } = this.form.getRawValue();
        const color = (rawColor || 'random') as PlayerColor;

        this.challengeService.sendChallenge(targetUsername, {
            timeControl: {
                limitSeconds,
                incrementSeconds
            },
            color,
            ttlSeconds: ttlSeconds > 0 ? ttlSeconds : undefined
        })
            .pipe(finalize(() => { this.loading = false; this.form.enable(); }))
            .subscribe({
                next: (challenge) => {
                    // Challenge sent successfully - navigate to challenges page to view status
                    this.form.reset();
                    this.closeChallengeDialog.emit();
                    void this.router.navigate(['/challenges']);
                },
                error: (error) => {
                    this.errorMessage = getErrorMessage(error, 'Failed to send challenge. Please try again.');
                }
            });
    }

    cancel(): void {
        this.form.reset();
        this.closeChallengeDialog.emit();
    }
}
