import { ISession } from "@models/Session.model";
import { persist, createJSONStorage } from "zustand/middleware";
import ApiRequest from "@services/Api.Service";
import { create } from "zustand";
import { DefaultMetricsModel, IMetrics } from "@core/Models/Metrics.model";
import { DefaultSubscriptionModel, ISubscriptionInfo } from "@core/Models/Subscription.Model";

export type LoginState = "started" | "success" | "sleep" | "error";

interface ISessionStore {
    loginState: LoginState;
    loading: boolean;
    setLoginState: (state: LoginState) => void;
    setLoged: (state: boolean) => void;
    setUserId: (userId: string) => void;
    setUserFullName: (userFullName: string) => void;
    setUserEmail: (userEmail: string) => void;
    setUser: (sessionData: ISession) => void;
    setSubscription: (subscription: ISubscriptionInfo) => void;
    setMetrics: (metrics: IMetrics) => void;
    checkSession: () => Promise<void>;
    clear: () => void;
    clearSubscription: () => void;
}

export type SessionState = ISession & ISessionStore;

const useSessionStore = create<SessionState>()((set) => ({
    loged: false,
    userId: "",
    userName: "",
    userFullName: "",
    userEmail: "",
    avatar: "",
    subscription: DefaultSubscriptionModel,
    organizationSubscriptions: {},
    metrics: DefaultMetricsModel,
    userToken: "",
    loginState: "sleep",
    loading: true,
    setLoginState: (state: LoginState) => set(() => ({ loginState: state })),
    setLoged: (state: boolean) => set(() => ({ loged: state })),
    setUserId: (userId: string) => set(() => ({ userId: userId })),
    setUserFullName: (userFullName: string) => set(() => ({ userFullName: userFullName })),
    setUserEmail: (userEmail: string) => set(() => ({ userEmail: userEmail })),
    setUser: (user: ISession) => set(() => ({ ...user })),
    setSubscription: (subscription: ISubscriptionInfo) =>
        set(() => ({ subscription: subscription })),
    setMetrics: (metrics: IMetrics) => set(() => ({ metrics: metrics })),
    checkSession: async () => {
        const token = useSessionTokenStore.getState().token;
        if (!token) {
            set({ loading: false });
            return;
        }

        try {
            const sessionData = await ApiRequest.post<ISession>("users/loginbytoken", {
                token,
            });

            set({ ...sessionData, loginState: "success" });
            useSessionTokenStore.getState().setToken(sessionData.userToken);
        } catch {
            set({
                loged: false,
                loginState: "sleep",
                userId: "",
                userEmail: "",
                userName: "",
                userFullName: "",
                avatar: "",
                subscription: DefaultSubscriptionModel,
                organizationSubscriptions: {},
                metrics: DefaultMetricsModel,
            });
            useSessionTokenStore.getState().setToken("");
        } finally {
            set({ loading: false });
        }
    },
    clear: () =>
        set(() => ({
            loged: false,
            loginState: "sleep",
            userId: "",
            userEmail: "",
            userName: "",
            userFullName: "",
            avatar: "",
            subscription: DefaultSubscriptionModel,
            organizationSubscriptions: {},
            metrics: DefaultMetricsModel,
        })),
    clearSubscription: () => set(() => ({ subscription: DefaultSubscriptionModel })),
}));

export interface ISessionTokenStore {
    token: string;
    setToken: (token: string) => void;
}

const useSessionTokenStore = create<ISessionTokenStore>()(
    persist(
        (set) => ({
            token: "",
            setToken: (token: string) => set(() => ({ token: token })),
        }),
        {
            name: "site-session-token",
            storage: createJSONStorage(() => localStorage),
        }
    )
);

export { useSessionStore, useSessionTokenStore };
