import axios, { AxiosError } from "axios";
import type { LoginInterface } from "./interfaces/login.interface";
import { useUtilsStore } from "@/pinia/utils/utils.store";
import type { ResponseLoginInterface } from "./interfaces/response_login.interface";
import type { UserLoginInterface } from "./interfaces/user_login.interface";
import type { UpdateUserInfoInterface } from "./interfaces/update_user_info.interface";


export const useLoginStore = defineStore("login_store", () => {
    const runtimeConfig = useRuntimeConfig();
    const { isExpiredToken } = useUtilsStore();
    const user = ref<UserLoginInterface>(null);

    /**
     * Inicia sesión en el sistema.
     * @param data 
     * @returns 
     */
    const login = async (data: LoginInterface): Promise<{ login: boolean, msg: string }> => {
        try {

            const created = await axios.post<ResponseLoginInterface>(`${runtimeConfig.public.api_url}/api/auth/login`, data);

            if (created.data) {
                setCookiesAuth(created.data.access_token, 'access_token');
                setCookiesAuth(created.data.refresh_token, 'refresh_token');
                setCookiesAuth(data.remember ? 'true' : 'false', 'remember');
                if(data.remember) {
                    setCookiesAuth(data.email, 'email');
                }

                axios.defaults.headers.common['Authorization'] = `Bearer ${created.data.access_token}`;

                return { login: true, msg: 'Sesión iniciada con éxito' };
            } else {
                return { login: false, msg: 'Hubo un error al activar la cuenta.' };
            }
        } catch (error) {
            if (error instanceof AxiosError) {
                if (error.response?.data.message) {
                    return { login: false, msg: error.response?.data.message };
                } else {
                    return { login: false, msg: 'Hubo un error al activar la cuenta.' };
                }
            } else {
                return { login: false, msg: 'Hubo un error al activar la cuenta.' }
            }
        }
    }

    /**
     * Obtiene los datos del usuario logeado
     * @returns 
     */
    const me = async (): Promise<UserLoginInterface> => {
        try {
            const access_token = useCookie('access_token');
            
            const me = await axios.get<UserLoginInterface>(`${runtimeConfig.public.api_url}/api/auth/me`, {
                headers: {
                    'Authorization': `Bearer ${access_token.value}`
                }
            });
            
            if (me.data) {
                user.value = me.data;
                return me.data;
            } else {
                user.value = null;
                return null;
            }
        } catch (error) {
            user.value = null;
            return null;
        }
    }

    /**
     * Setea la cookie cuando se hace "login" ó "renew"
     * @param cookie_value 
     * @param name_cookie 
     */
    const setCookiesAuth = (cookie_value: string, name_cookie: string) => {
        const cookie = useCookie(name_cookie, {
            path: '/',
            maxAge: 365 * 24 * 60 * 60,
            domain: runtimeConfig.public.cookies_domain,
            sameSite: 'lax',
        })
        cookie.value = cookie_value;
    }

    /**
     * Elimina la cookie seteandola como null;
     * @param name_cookie 
     */
    const deleteCookieAuth = (name_cookie: string) => {
        const cookie = useCookie(name_cookie);
        cookie.value = null;
    }

    /**
     * Obtiene la sesión activa de un usuario.
     * @returns 
     */
    const getUserSessionActive = async () => {
        const access_token = useCookie('access_token').value || '';
        const refresh_token = useCookie('refresh_token').value || '';
        const not_logout = useCookie('remember').value || '';

        if (!access_token && !refresh_token) {
            return false;
        }

        const time_remaining_access_token = isExpiredToken(access_token)
        const time_remaining_refresh_token = isExpiredToken(refresh_token);

        /**
         * Si "time_remaining_access_token" es diferente de "null" ó "0"
         * Se hace una petición para renovar el access_token
         */
        if (time_remaining_access_token) {
            setTimeout(async () => {
                // Si el acces token (1 hora) un no expira se refresca el access token
                await userLoginWithRefreshToken(refresh_token);
            }, time_remaining_access_token);
            return true;
        } else if (time_remaining_refresh_token) {
            //Al momento de iniciar sesión si no se marca la casilla deberá ser false
            if (!not_logout) {
                return false;
            }

            //Si el usuario marca "Mantener sesion", se intenta iniciar sesion con un refresh_token
            const logued = await userLoginWithRefreshToken(refresh_token);

            if (!logued) {
                return false;
            }

            return true;
        } else {
            return false;
        }
    }

    /**
     * Renueva el "access_token" ó "refresh_token"
     * @param refresh_token
     * @returns
     */
    const userLoginWithRefreshToken = async (refresh_token: string): Promise<boolean> => {
        try {
            const response = await axios.post(`${runtimeConfig.public.api_url}/api/auth/token`, { refresh_token });

            setCookiesAuth(response.data.access_token, 'access_token');
            setCookiesAuth(response.data.refresh_token, 'refresh_token');

            return true;
        } catch (error) {
            return false;
        }
    }

    const updateUserInfo = async (data: UpdateUserInfoInterface) => {
        try {

            const access_token = useCookie('access_token').value;

            const updated = await axios.put<UserLoginInterface>(`${runtimeConfig.public.api_url}/api/auth/user`, data, {
                headers: {
                    'Authorization': `Bearer ${access_token}`,
                }
            });

            if(updated.data) {
                user.value = updated.data;
                return true;
            } else {
                return false;
            }
        } catch (error) {
            return false;
        }
    }

    /**
     * Cierra la sesión del usuario eliminando las cookies
     */
    const logout = () => {
        deleteCookieAuth('access_token');
        deleteCookieAuth('refresh_token');
        navigateTo('/');
    }

    return {
        login,
        me,
        getUserSessionActive,
        logout,
        updateUserInfo,

        user,
    }
})