import { HttpErrorResponse } from "@angular/common/http";
import { Component, OnDestroy, OnInit, ViewEncapsulation } from "@angular/core";
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
import { ApiResources, UtilHelper } from "@shared/helpers";
import { IResource, OTPResponse, Page } from "@shared/models";
import { HttpService, NotifyService, ResourceService } from "@shared/services";
import { CompareValidator, EmailValidator, MobileValidator } from "@shared/validators";
import { finalize, takeUntil } from "rxjs/operators";

class ForgotRequest {
    type: string;
    username: string;
    countryId: number;
    password: string;
    accountTypes: Array<number>;
    accountId: number;
    fullName: string;
}

@Component({
    templateUrl: "./forgot-password.html",
    encapsulation: ViewEncapsulation.None
})
export class ForgotPasswordPage implements OnInit, OnDestroy {
    page: Page;
    step: number;

    loadingCountries: boolean;
    countries: Array<IResource>;

    forgotForm: FormGroup;
    otp: string;
    otpExpiresIn: number;
    successMessage: string;
    submitting: boolean;
    submitted: boolean;

    constructor(
        private readonly httpService: HttpService,
        private readonly notifyService: NotifyService,
        private readonly resourceService: ResourceService,
        private readonly formBuilder: FormBuilder
    ) {
        this.page = new Page();
        this.buildForm();
    }

    private buildForm() {
        this.step = 1;
        this.forgotForm = this.formBuilder.group({
            type: [null],
            accountId: [0],
            fullName: [null],
            countryId: [null, [Validators.required]],
            username: ["", [Validators.required]],
            password: "",
            confirmPassword: ""
        }, { validator: CompareValidator.compare("password", "confirmPassword") });

        this.forgotForm.get("countryId").valueChanges.subscribe(() => { this.forgotForm.get("username").updateValueAndValidity(); });

        this.forgotForm.get("username").valueChanges.subscribe((username: string) => {
            const typeControl = this.forgotForm.get("type");
            const usernameControl = this.forgotForm.get("username");

            if (username) {
                const type = /^[0-9]+$/.test(username) ? "M" : "E";
                if (type === "M") {
                    usernameControl.setValidators([Validators.required, MobileValidator.isValid]);
                } else {
                    usernameControl.setValidators([Validators.required, EmailValidator.isValid]);
                }
                typeControl.patchValue(type);
            } else {
                typeControl.patchValue(null);
                usernameControl.setValidators([Validators.required]);
            }
        });
    }

    private fetchCountries() {
        this.loadingCountries = true;
        this.resourceService.countries()
            .pipe(finalize(() => { this.loadingCountries = false }))
            .pipe(takeUntil(this.page.unSubscribe))
            .subscribe((response: Array<IResource>) => {
                this.countries = response;
                this.forgotForm.get("countryId").patchValue(response[0].id);
            });
    }

    getModel() {
        return {
            username: this.forgotForm.get("username").value,
            countryCode: this.forgotForm.get("type").value === "M" ? this.countries.find(m => m.id === this.forgotForm.get("countryId").value).optionalText : "",
            countryId: this.forgotForm.get("type").value === "M" ? this.forgotForm.get("countryId").value : 0
        }
    }

    get countryCode() {
        return this.forgotForm.get("countryId").value ? this.countries.find(m => m.id === this.forgotForm.get("countryId").value).optionalText : "";
    }

    get form() {
        return this.forgotForm.controls;
    }

    onSubmit() {
        this.submitted = true;
        if (!this.forgotForm.valid) {
            this.notifyService.warningToast("PLEASE ENTER VALID EMAILId/ MOBILE NUMBER")
            return;
        }

        if (this.step === 3 && (this.forgotForm.controls.password.errors || this.forgotForm.controls.confirmPassword.errors)) {
            return;
        }

        const model = UtilHelper.clone(this.forgotForm.getRawValue()) as ForgotRequest;
        model.username = model.type && model.type === "M" ? model.countryId + ":" + model.username : model.username;
        //model.accountTypes = [Role.SuperAdmin, Role.Administrator, Role.Support, Role.Accountant, Role.SymptomCreator, Role.SymptomManager];
        delete model.type;
        delete model.countryId;
        delete model.fullName;

        this.successMessage = undefined;
        this.submitting = true;

        this.httpService
            .post<string | OTPResponse>(ApiResources.getURI(ApiResources.account.base, ApiResources.account.forgotPassword), model, false)
            .pipe(finalize(() => { this.submitted = false, this.submitting = false }))
            .pipe(takeUntil(this.page.unSubscribe))
            .subscribe({
                next: (response: (string | OTPResponse)) => {
                    if (typeof response === "object") {
                        const otpResponse = response as OTPResponse;
                        if (otpResponse.error) {
                            this.notifyService.warning(otpResponse.errorDescription);
                        } else {
                            this.otp = otpResponse.otp;
                            this.otpExpiresIn = otpResponse.otpExpiresIn;
                            this.forgotForm.get("accountId").patchValue(otpResponse.accountId);
                            this.forgotForm.get("fullName").patchValue(otpResponse.fullName);
                            this.step = 2;
                        }
                    } else {
                        this.successMessage = response as string;
                    }
                },
                error: (error: HttpErrorResponse) => {
                    const errorMessage = UtilHelper.handleError(error);
                    if (errorMessage) {
                        this.notifyService.warning(errorMessage);
                    } else {
                        this.notifyService.defaultError();
                    }
                }
            });
    }

    onValidateOTP(validated: boolean) {
        if (validated) {
            this.step = 3;

            const passwordControl = this.forgotForm.get("password");
            passwordControl.patchValue(null);
            passwordControl.setValidators([Validators.required, Validators.minLength(4)]);
            passwordControl.updateValueAndValidity();

            const confirmPasswordControl = this.forgotForm.get("confirmPassword");
            confirmPasswordControl.patchValue(null);
            confirmPasswordControl.setValidators([Validators.required, Validators.minLength(4)]);
            confirmPasswordControl.updateValueAndValidity();
        }
    }

    ngOnInit() {
        this.fetchCountries();
    }

    ngOnDestroy() {
        this.page.unsubscribeAll();
    }
}