import { Component, ElementRef, QueryList, ViewChildren, Output, EventEmitter, Input } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ButtonsModule } from '@progress/kendo-angular-buttons';
import { IndicatorsModule } from '@progress/kendo-angular-indicators';
import { AuthService, LoginCredentials, LoginResultType } from '../services/auth.service';

const CODE_LENGTH = 6;

@Component({
    selector: 'app-mfa-dialog',
    standalone: true,
    imports: [
        CommonModule,
        FormsModule,
        ButtonsModule,
        IndicatorsModule
    ],
    templateUrl: './mfa-dialog.component.html',
    styleUrls: ['./mfa-dialog.component.scss']
})
export class MfaDialogComponent {
    @ViewChildren('codeInput') codeInputs!: QueryList<ElementRef>;
    @Output() mfaSuccess = new EventEmitter<any>();
    @Output() mfaCancel = new EventEmitter<void>();
    @Input() visible = false;

    token: string = '';
    userInputCodes: (string | null)[] = [];
    userInputCodes2: (string | null)[] = [];
    loginData!: LoginCredentials;
    processing = false;
    allowSubmit = false;
    isInvalidCode = false;
    resendCountDown = 30;

    constructor(private authService: AuthService) { }

    ngOnInit() {
        for (let i = 0; i < CODE_LENGTH; i++) {
            this.userInputCodes.push(null);
            this.userInputCodes2.push(null);
        }
        this.setReSendCountDown();
    }

    pasteCode(index: number, event: ClipboardEvent) {
        event.preventDefault();
        const data = event.clipboardData?.getData('text/plain') || '';
        let pasteCode = data.replace(new RegExp("[^0-9]", 'g'), "");
        for (let i = index; i < CODE_LENGTH; i++) {
            if (pasteCode.length > i) {
                const code = pasteCode[i];
                let input = this.codeInputs.find((element, j) => j === i);
                if (input) {
                    input.nativeElement.value = code;
                    this.userInputCodes[i] = code;
                }
            }
        }
        this.validate(5);
    }

    public onKeyDown(index: number, e: KeyboardEvent): void {
        const el: HTMLInputElement = e.target as HTMLInputElement;
        if (e.ctrlKey && e.key.toUpperCase() == 'V') {
            return;
        } else {
            let nextFocusInput: ElementRef | undefined = undefined;
            switch (e.key) {
                case 'ArrowLeft':
                    nextFocusInput = this.getInputElements(index, -1);
                    if (nextFocusInput) nextFocusInput.nativeElement.focus();
                    break;
                case 'ArrowRight':
                    nextFocusInput = this.getInputElements(index, 1);
                    if (nextFocusInput) nextFocusInput.nativeElement.focus();
                    break;
                case 'Backspace':
                    if (el.value) {
                        el.value = '';
                    } else {
                        nextFocusInput = this.getInputElements(index, -1);
                    }
                    break;
                case 'Delete':
                    el.value = '';
                    break;
                default:
                    break;
            }

            if (nextFocusInput) {
                nextFocusInput.nativeElement.focus();
                return;
            }

            let isReplacing = el.selectionStart != el.selectionEnd;

            if (this.isEditingKeyPress(e)) {
                e.preventDefault();
                if (new RegExp("[0-9]", 'g').test(e.key)) {
                    this.userInputCodes[index] = e.key;
                    el.value = e.key;
                    let nextInput = this.getInputElements(index, 1);
                    if (nextInput) nextInput.nativeElement.focus();
                } else {
                    el.value = '';
                    this.userInputCodes[index] = null;
                }
            }
        }

        this.isInvalidCode = false;
        this.validate(index);
    }

    private getInputElements(index: number, indexOffset: number): ElementRef | undefined {
        let nextInput = this.codeInputs.find((element, i) => i === (index + indexOffset));
        return nextInput;
    }

    private isEditingKeyPress(e: KeyboardEvent): boolean {
        return e.key.length === 1 || e.key === 'Backspace' || e.key === 'Delete' || e.key === 'ArrowLeft' || e.key === 'ArrowRight';
    }

    validate(focusIndex: number) {
        this.allowSubmit = !this.userInputCodes.some(n => n == null);
        this.token = this.userInputCodes.map(n => n != null ? n : '').join('');
        if (this.token && this.token.length == 6 && focusIndex == 5) {
            this.submitCode();
        }
    }

    close() {
        this.visible = false;
        this.mfaCancel.emit();
    }

    show() {
        this.visible = true;
        this.resetForm();
    }

    hide() {
        this.visible = false;
    }

    resetForm() {
        this.userInputCodes = [];
        this.userInputCodes2 = [];
        this.token = '';
        this.isInvalidCode = false;
        this.processing = false;
        this.allowSubmit = false;

        for (let i = 0; i < CODE_LENGTH; i++) {
            this.userInputCodes.push(null);
            this.userInputCodes2.push(null);
        }

        // Focus on first input
        setTimeout(() => {
            const firstInput = document.querySelector('.mfa-input:first-child') as HTMLInputElement;
            if (firstInput) {
                firstInput.focus();
            }
        }, 100);
    }

    submitCode() {
        this.processing = true;
        this.loginData.mfaCode = this.token;

        // Handle login MFA verification
        {
            this.authService.login(this.loginData).subscribe({
                next: (result) => {
                    this.processing = false;

                    if (result.result === LoginResultType.Success) {
                        this.mfaSuccess.emit(result.responseData);
                        this.visible = false;
                    } else {
                        this.isInvalidCode = true;
                    }
                },
                error: (error) => {
                    this.processing = false;
                    this.isInvalidCode = true;
                    console.error('MFA verification error:', error);
                }
            });
        }
    }

    setReSendCountDown() {
        if (this.resendCountDown > 0) {
            setTimeout(() => {
                this.resendCountDown--;
                this.setReSendCountDown();
            }, 1000);
        }
    }

    resendMFCode() {
        this.resendCountDown = 30;
        this.loginData.mfaCode = '';

        // Simulate resend MFA code - replace with actual service call
        console.log('Resending MFA code to:', this.loginData.email);
        //TODO: Implement resend MFA code for regular login
        this.setReSendCountDown();
    }

    public get resendCodeText(): string {
        return 'Resend Code' + (this.resendCountDown > 0 ? ` (${this.resendCountDown})` : '');
    }
}
