import { clearCredentials, selectCurrentToken, selectCurrentUser, setCredentials } from '@/features/auth/authSlice';
import { EVENT_TYPES, eventEmitter } from '@/lib/event-util';
import { fetchApi, refreshAuthToken } from '@/lib/server-api-util';
import { store } from '@/store';
import { User } from '@/types/user';
import React, { createContext, ReactNode, useContext, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';

interface AuthContextType {
    user: User | null;
    login: (user: User, jwt: string) => void;
    logout: () => void;
    jwt: string | null;
    isGuester: () => Promise<boolean>;
    isFormalUser: (userMessage: User | null) => boolean;
}

const AuthContext = createContext<AuthContextType | undefined>(undefined);

export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
    const dispatch = useDispatch();
    const user = useSelector(selectCurrentUser);
    const jwt = useSelector(selectCurrentToken);

    useEffect(() => {
        // 检查 Redux store 中是否已有 token
        const refreshTokenAction = async () => {
            const token = store.getState().auth.token;
            if (token) {
                // 验证当前 token 是否有效
                fetchApi('/user/identity-check', {}, false)
                    .catch(async (error) => {
                        console.error("JWT validation failed, attempting to refresh token...");
                        try {
                            // 尝试刷新 token
                            await refreshAuthToken("Token expired");
                            console.log("Token refreshed successfully");
                            // Token 刷新成功，不需要做其他操作
                        } catch (refreshError) {
                            // 刷新 token 失败，才进行登出操作
                            console.error("Token refresh failed, logging out", refreshError);
                            logout();
                        }
                    });

            } else {
                try {
                    // 尝试刷新 token
                    await refreshAuthToken("Token expired");
                    console.log("Token refreshed successfully");
                    // Token 刷新成功，不需要做其他操作
                } catch (refreshError) {
                    // 刷新 token 失败，才进行登出操作
                    console.error("Token refresh failed, logging out", refreshError);
                    logout();
                }
            }
        }

        refreshTokenAction();
    }, [dispatch]);

    const login = (newUser: User, newJwt: string) => {
        // 更新 Redux store
        dispatch(setCredentials({
            user: newUser,
            token: newJwt
        }));

        // 触发事件通知
        eventEmitter.emit(EVENT_TYPES.USER_INFO_UPDATED, newUser);
    };

    const logout = () => {
        // 清除 Redux store 中的认证信息
        dispatch(clearCredentials());

        // 触发事件通知
        eventEmitter.emit(EVENT_TYPES.USER_INFO_UPDATED, null);

    };

    // 判断是否是游客身份
    const isGuester = async () => {
        // 调用接口判断是否是游客
        try {
            await fetchApi(`/iam/identity-check`, {
                method: 'POST',
            }, false);
            user?.email === ""
            return false
        } catch (error) {
            return true;
        }
    }
    // 判断是否是正式用户 手机号注册和email注册都为正式用户
    const isFormalUser = (userMessage: User | null) => {
        if (userMessage?.account) {
            if (userMessage?.account?.includes("@")) {
                return true
            } else if (/^1[3-9]\d{9}$/.test(userMessage?.account)) {
                return true
            } else {
                return false
            }
        }
        // 没有用户信息
        return false
    }
    return (
        <AuthContext.Provider value={{ user, login, logout, jwt, isGuester, isFormalUser }}>
            {children}
        </AuthContext.Provider>
    );
};

export const useAuth = () => {
    const context = useContext(AuthContext);
    if (context === undefined) {
        throw new Error('useAuth must be used within an AuthProvider');
    }
    return context;
};