import Loader from "@/components/loader";
import React, {createContext, useEffect, useReducer} from "react";
import {auth, getUserInfo} from "@/service/api/user.ts";
import {getAuthToken, setAuthToken} from "@/hooks/useAuth.ts";
import {getRoleByUsername} from "@/contexts/auth/role.ts";


const AuthContext = createContext<AuthContextType | null>(null)

const initialState: AuthProps = {
	isLoggedIn: false,
	isInitialized: false,
	user: null
};
const authReducer = (state: AuthProps, action: { action?: string, payload: Partial<AuthProps> }) => {
	return {
		...state,
		...action.payload,
	}
}

const UserRoleStorageKey = 'user-current-role';

function getCurrentRole(username: string) {
	return (localStorage.getItem(UserRoleStorageKey) || getRoleByUsername(username)) as UserRole
}

export function setCurrentRole(role: UserRole) {
	localStorage.setItem(UserRoleStorageKey, role)
}

function removeRoleStorage() {
	localStorage.removeItem(UserRoleStorageKey)
}

function getInitUserData(user: UserProfile) {
	const {roles} = user;
	const role = !roles || roles.length === 0 ? 'staff' : (
		roles.includes('root') ? 'root' : (
			roles.includes('fo') ? 'fo' : 'ro'
		)
	) as UserRole

	return {
		...user,
		origin_role: role,
		role: role == 'root' ? (getCurrentRole(user.username) || role) : role
	}
}

export const AuthProvider = ({children}: { children: React.ReactNode }) => {
	const [state, dispatch] = useReducer(authReducer, initialState);

	// MOCK INIT DATA
	const refreshUserInfo = async ()=>{
		const user = await getUserInfo();
		dispatch({
			action: 'refresh',
			payload: {
				isLoggedIn: !!user,
				user: getInitUserData(user)
			}
		})
	}
	const init = async () => {
		const token = getAuthToken();
		if (!token) {
			dispatch({
				payload: {
					isInitialized: true,
				}
			})
			return 'initialized'
		}
		getUserInfo().then(user => {
			dispatch({
				action: 'init',
				payload: {
					isInitialized: true,
					isLoggedIn: !!user,
					user: getInitUserData(user)
				}
			})
		}).finally(() => {
			dispatch({
				payload: {
					isInitialized: true,
				}
			})
		})
		return 'initialized'
	}
	// 登录
	const login = async (code: string, state: string) => {
		const user = await auth(code, state)
		// 保存token
		setAuthToken(user.token, user.expiration_time ? (new Date(user.expiration_time)).getTime() : -1);

		//
		dispatch({
			action: 'login',
			payload: {
				isLoggedIn: true,
				user: getInitUserData(user)
			}
		})
	}
	// 登出
	const logout = async () => {
		setTimeout(() => {
			const a = document.createElement('a')
			a.setAttribute('href', 'https://portal.chuhai.edu.hk/signout')
			a.setAttribute('target', '_blank')
			a.click()
		}, 0)
		setAuthToken(null)
		removeRoleStorage()
		dispatch({
			action: 'logout',
			payload: {
				isLoggedIn: false,
				user: null
			}
		})
	}
	const mockLogin = async () => {
		console.log('mock login')
	}

	const updateUser = async (user: Partial<UserProfile>) => {
		dispatch({
			action: 'updateUser',
			payload: {
				user: {
					...state.user,
					...user
				} as never,

			}
		})
	};

	useEffect(() => {
		init().then(console.log)
	}, [])

	// 判断是否已经初始化
	if (state.isInitialized !== undefined && !state.isInitialized) {
		return <Loader/>;
	}
	return (<AuthContext.Provider value={{
		...state,
		login, logout,
		mockLogin, updateUser,
		refreshUserInfo
	}}>{children}</AuthContext.Provider>)
}
export default AuthContext