import { MainStateManager } from "../MainStateManager";
import { ElementsOfFormFactory } from "../Page/ElementsOfFormFactory";

import { AxiosError } from "axios";
import { CheckBoxFactory } from "../ComponentFactory/CheckBoxFactory";
import { UserBoxFactory } from "../ComponentFactory/UserBoxFactory";

import { MenuFactory } from "./Menus/1-MenuFactory";

import { ISettingInfo } from "./Models/SettingInfo";
import { FiscalYear, IFiscalYearsInfo } from "./Models/FiscalYearsInfo/FiscalYearsInfo";
import { ISubSystemsInfo } from "./Models/SubSystemsInfo/SubSystemsInfo";
import { useAxios, useUrls } from "./Models/StorageManager/TokenInfo";
import { IUserInfo } from "./Models/UserInfo/UserInfo";
import { LoginByToken } from "./Logins/Token/LoginByToken";
import { LoginByUserPass } from "./Logins/UserPass/LoginByUserPass";


export interface ILoginResponseData {
    fiscalYearsInfo: IFiscalYearsInfo,
    userInfo: IUserInfo,
    settingInfo: ISettingInfo,
    subSystemsInfo: ISubSystemsInfo,
}
export interface ILoginResponse {
    isSuccess: boolean,
    message: string,
    token: string,

    data: ILoginResponseData,
}

export class AuthFactory {
    public get any() {
        return this as any;
    }
    #urls = useUrls('BaseCode', 'auth');
    #apiAxios = useAxios(this.#urls);

    public forceUpdate = () => { }
    public searchBoxRef?: React.RefObject<HTMLInputElement>;
    public cach: {} = {};
    public userRoutes: any[] = [];

    public getUser = () => {
        return this.any['userBoxArmisa'] as UserBoxFactory;
    }

    public getPass = () => {
        return this.any['passwordBoxArmisa'] as UserBoxFactory;
    }

    public getRememberMe = () => {
        return this.any['RemeberMe'] as CheckBoxFactory;
    }

    public elementsOfForm: ElementsOfFormFactory;
    public menuFactory: MenuFactory;
    public afterLoginSuccess?: (response: any) => void;
    constructor(public mainStateManager: MainStateManager) {
        this.menuFactory = new MenuFactory(this.mainStateManager, this);
        this.elementsOfForm = new ElementsOfFormFactory(this);
    }

    public loginByToken = () => {
        LoginByToken.createNew(this)?.login();
    }

    public loginByUserPass = () => {
        LoginByUserPass.createNew(this)?.login();
    }

    #afterLoginSuccess = (response: ILoginResponse) => {
        if (typeof this.afterLoginSuccess === 'function') {
            this.afterLoginSuccess(response);
        }
    }

    public get isAtunticated(): boolean {
        return this.mainStateManager.userInfo.isAuthenticated();
    }

    /* @internal */
    public logedIn = (response: ILoginResponse, rememberMe: boolean, path: string) => {
        this.deserialize(response, rememberMe);
        this.#afterLoginSuccess(response);
        this.mainStateManager.push(path);
    }

    public signOut = () => {
        this.mainStateManager.tokenInfo.signOut();
        this.mainStateManager.settingInfo.signOut();
        this.mainStateManager.subSystemsInfo.signOut();
        this.mainStateManager.userInfo.signOut();

        this.mainStateManager.push('/login');
        this.mainStateManager.forceUpdate();

    }

    public selectNewActiveFiscalYear = (currentRow: FiscalYear) => {
        this.elementsOfForm.showWaitingFormSpinner();

        this.#apiAxios.get<ILoginResponse>(`${this.#urls.selectActiveYear}?FK_tbl_axData=${currentRow.id}`)
            .then((res) => {
                if (res.status == 200 && res.data.isSuccess) {
                    this.deserialize(res.data);

                    if (typeof this.afterLoginSuccess === 'function') {
                        this.afterLoginSuccess(res.data);
                    }
                    this.elementsOfForm.closeWaitingFormSpinner();
                    // this.close();

                } else {
                    console.error("error on login user error : ", res.data);
                    this.elementsOfForm.closeWaitingFormSpinner();
                    this.elementsOfForm.showInvalidArgumentMessageBox(res.data.message);
                }
            })
            .catch((error: AxiosError) => {
                console.error("exception error on login user error : ", error);
                this.elementsOfForm.closeWaitingFormSpinner();
                this.elementsOfForm.showErrorMessageBox(error);
            });
    }


    public selectNewActiveSystems = () => {
        this.elementsOfForm.showFullScreenWaittingSpinner();
        this.#apiAxios.post<ILoginResponse>(this.#urls.login, this.mainStateManager.subSystemsInfo.selected)
            .then((res) => {
                if (res.status == 200 && res.data.isSuccess) {
                    this.deserialize(res.data);

                    if (typeof this.afterLoginSuccess === 'function') {
                        this.afterLoginSuccess(res.data);
                    }
                    this.elementsOfForm.closeFullScreenWaittingSpinner();
                    this.menuFactory.forceUpdateAfterSystemsChange();

                } else {
                    console.error("error on select active user error : ", res.data);
                    this.elementsOfForm.closeFullScreenWaittingSpinner();
                    this.elementsOfForm.showInvalidArgumentMessageBox(res.data.message);
                }
            })
            .catch((error: AxiosError) => {
                console.error("exception error on select active user error : ", error);
                this.elementsOfForm.closeFullScreenWaittingSpinner();
                this.elementsOfForm.showErrorMessageBox(error);
            });


    }

    private deserialize = (data: ILoginResponse, rememberMe: boolean = false) => {
        this.mainStateManager.tokenInfo.deserialize(data.token, rememberMe);
        this.mainStateManager.settingInfo.deserialize(data.data.settingInfo);
        this.mainStateManager.userInfo.deserialize(data.data.userInfo);
        this.mainStateManager.fiscalYearsInfo.deserialize(data.data.fiscalYearsInfo);
        this.mainStateManager.subSystemsInfo.deserialize(data.data.subSystemsInfo);
    }
}