/* eslint-disable @typescript-eslint/no-unused-vars */
import React, {PropsWithChildren, useEffect, useState} from "react";
import * as authAPI from "../API/user";
import {checkExtraAuth, getProfilePicture, logout, updateQuickAccess} from "../API/user";
import {Outlet, useNavigate} from "react-router-dom";
import {AppSettings, EgovUser, MicroservicePermissions, Permissions, Translations} from "../models/EgovUser";
import LoadingPage from "../components/UI/LoadingPage/LoadingPage";
// import {cacheClear} from '../API/axios'
import {beamsClient, unsubscribeFromAllChannels} from "../services/pusher";
import axios from "axios";


/**
 * creates permissions per microservice per user
 * eg: rescom = {
 *     director.erga,
 *     president.simvaseis
 * }
 */
const transformPermissions = (permissions: Permissions): MicroservicePermissions => {
    const microservice_permissions: MicroservicePermissions = {};

    Object.entries(permissions).map(([role, rolePermissions]) => {
        Object.keys(rolePermissions).forEach((per: string) => {
            const [ms, module] = per.split('.');
            if (!(ms in microservice_permissions)) {

                // @ts-ignore
                microservice_permissions[ms] = [];
            }
            // @ts-ignore
            microservice_permissions[ms].push(`${role}.${module}`);
        });
    });

    /**
     * we handle the settings as an ms but its not defined in the backend
     */

    return microservice_permissions;
};

interface AuthContextInterface {
    isAuthenticated: boolean;
    hasExtraAuth: boolean
    currentUser: EgovUser | null;
    translations: Translations | null;
    // appSettings: AppSettings | null
    logoutUser: () => void;
    loginUser: (user: EgovUser, translations: any) => void;
    addQuickAccess: (role: string, permission: string) => void;
    removeQuickAccess: (key: string) => void;
    reOrderQuickAccess: (q: string[]) => void;
    userAvatar: File | null
    setUserAvatar: (avatar: File | null) => void; // New function to set the avatar
    updateProfileSetting: (setting: string, value: boolean) => void;
    setTourVisible: (visible: boolean) => void;
    tourVisible: boolean;
    setHasExtraAuth: (a: boolean) => void
    globalSettings: AppGlobalSettings | null;

}

interface AppGlobalSettings {
    alfaenavideourl?: { status: string };
    allow_sms?: { status: number };
    disable_login?: { status: number; message: string };
    ldap_down?: { status: number; message: string };
    invitation_duration_days?: { status: number };
    verification_code_digits?: { status: number };
    verification_code_expiration_time?: { status: number };
    [key: string]: any; // for any future settings
}


/**
 *
 *
 * THIS CONTEXT IS THE FIRST HING THAT RUNS (KINDA) WHEN THE APP LOAD
 * It make a request to api/session to check if the user is authenticated (browser has session cookie)
 *
 * AUTH CONTEXT HANDLES
 * if user is authenticated
 * personal data about user
 * user permissions data (modules and services)
 * personal user settings
 * user's quick access
 *
 *
 * ...and
 * Data about ALL the possible modules and services
 *
 *
 */

const AuthContext = React.createContext({} as AuthContextInterface);
export const AuthContextProvider: React.FC<PropsWithChildren> = (props) => {
    const navigate = useNavigate();
    /** Not really a part of User Context, used to display loading page while we wait fo the session request */
    const [requestPending, setPendingRequest] = useState(true);
    /** All the information about the logged in User */
    const [currentUser, setCurrentUser] = useState<EgovUser | null>(null);
    /** Text translations, includes view names of thins like Applicationa Service and Role, this is included in the session repsonse  */
    const [translations, setTranslations] = useState<Translations | null>(null);
    const [isAuthenticated, setIsAuthenticated] = useState(false);
    /** The tour is a guide that users see on login, they can be deactivated and we store their preferences in Local Storage */
    const [tourVisible, setTourVisible] = useState(true);
    const [userAvatar, setUserAvatar] = useState<File | null>(null); // New state for the avatar
    const [hasExtraAuth, setHasExtraAuth] = useState<boolean>(false); // New state for the avatar
    const [appSettings, setAppSettings] = useState<AppSettings | null>(null)
    const [globalSettings, setGlobalSettings] = useState<AppGlobalSettings | null>(null);
    useEffect(() => {
        setPendingRequest(true);
        (async () => {
            // setPendingRequest(true)
            // try {
            //
            //     const settings = await authAPI.getSettings()
            //     const loginIsDisabled = settings.data['disable_login']?.status === 1 ?? false;
            //     const ldapIsDown = settings.data['ldap_down']?.status === 1 ?? false;
            //     setAppSettings({
            //         loginIsDisabled,
            //         ldapIsDown
            //     })
            //     /**
            //      * LOOK IF THE LOGIN DISABLED SETTING IS TRUE AND REDIRECT TO LOGIN
            //      */
            //     // if (settings.data['disable_login'].status == 1) {
            //     //     await authAPI.logout()
            //     //     setPendingRequest(false);
            //     //     navigate("/login");
            //     // }
            //
            // } catch (error) {
            //     setPendingRequest(false);
            //     navigate("/login");
            // } finally {
            //
            //
            // }


            const res = await authAPI.checkAuth().then(
                (res) => {
                    if (res.status === 401) return;

                    const newUser = {...res.data.user};
                    const translations = {...res.data.translations};
                    setUserContext(newUser, translations);
                    setHasExtraAuth(res.data.extra_auth ?? false);
                    setGlobalSettings(res.data.settings?.settings ?? null);
                },
                (err) => {}
            );

            setPendingRequest(false);
        })();
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

    /**
     * this is called after manually login or after checking sessions and user is logged in
     */
    const setUserContext = (user: EgovUser, translations: Translations) => {
        const microservice_permissions = transformPermissions(JSON.parse(JSON.stringify(user.permissions)));
        user.microservice_permissions = microservice_permissions;

        setCurrentUser(user);
        setIsAuthenticated(true);

        /***
         * Translation for settings are defined in the frontend for now (::
         */
        // translations.microservices.settings = {
        //     view_name: 'Ρυθμίσεις',
        //     description: 'Ρυθμίσεις',
        // }
        // translations.modules['settings.profile'] = {
        //     view_name: 'Ρυθμίσεις Προφίλ',
        //     description: 'Ρυθμίστε τις επιλογές',
        // }
        // translations.modules['settings.notifications'] = {
        //     view_name: 'Ρυθμίσεις Ενημερώσεων',
        //     description: 'Ρυθμίστε τις επιλογές',
        // }
        // translations.modules['settings.reminders'] = {
        //     view_name: 'Ρυθμίσεις Υπενθυμίσεων',
        //     description: 'Ρυθμίστε τις επιλογές',
        // }


        setTranslations(translations);
        fetchUserAvatar()
    };

    const fetchUserAvatar = async () => {
        try {
            const res = await getProfilePicture()
            if (res.status === 200) {
                setUserAvatar(res.data);
            } else {
                setUserAvatar(null)
            }
        } catch (error) {
            if (axios.isCancel(error)) return; // silently ignore cancellations
            setUserAvatar(null);
        }
    }

    const addQuickAccess = async (role: any, permission: any) => {
        // const [service, module, right] = permission.split('.')
        const key = role + '.' + permission;
        if (!currentUser || currentUser.quickAccess.includes(key)) return;
        const newQuick = [...currentUser.quickAccess]
        newQuick.push(key)

        setCurrentUser({
            ...currentUser,
            quickAccess: newQuick
        })

        await updateQuickAccess(newQuick)
    }

    const removeQuickAccess = async (key: string) => {

        if (!currentUser) return;
        const newQuick = currentUser.quickAccess.filter(quick => quick !== key)

        setCurrentUser({
            ...currentUser,
            quickAccess: newQuick
        })
        await updateQuickAccess(newQuick)
    }

    const reOrderQuickAccess = async (newQuick: string[]) => {

        if (!currentUser) return;

        setCurrentUser({
            ...currentUser,
            quickAccess: newQuick
        })
        await updateQuickAccess(newQuick)
    }

    const updateProfileSetting = (setting: string, value: boolean) => {

        if (!currentUser) return;
        const newProfileSettings = {...currentUser?.profile_settings}
        if (!(setting in newProfileSettings)) return
        newProfileSettings[setting] = value;
        const newUser = currentUser
        newUser.profile_settings = newProfileSettings
        setCurrentUser(newUser)
    }

    return (
        <AuthContext.Provider
            value={{
                globalSettings,
                currentUser: currentUser,
                translations: translations,
                isAuthenticated: isAuthenticated,
                hasExtraAuth: hasExtraAuth,
                tourVisible: tourVisible,
                setTourVisible: setTourVisible,
                // appSettings:appSettings,
                userAvatar: userAvatar,
                logoutUser: async () => {
                    await logout()
                    unsubscribeFromAllChannels()
                    setCurrentUser(null);
                    setIsAuthenticated(false);
                    setUserAvatar(null);
                    setTourVisible(true);
                    // cacheClear();
                    if (beamsClient !== null) await beamsClient.stop()
                    window.location.href = '/';
                },
                loginUser: (user, translations) => {
                    const newUser = {...user};
                    setUserContext(newUser, translations);
                    navigate("/dashboard");
                },
                addQuickAccess: addQuickAccess,
                removeQuickAccess: removeQuickAccess,
                reOrderQuickAccess: reOrderQuickAccess,
                updateProfileSetting: updateProfileSetting,
                setUserAvatar: setUserAvatar, // Provide the setAvatar function
                setHasExtraAuth: setHasExtraAuth
            }}
        >
            {requestPending ? <LoadingPage/> : <Outlet/>}
        </AuthContext.Provider>
    );
};

export default AuthContext;

