import { atom, useAtomValue, setAtomValue } from "../lib/atom.ts";

type LoginLocalStorage = {
	username: string;
	permission: string[];
	accessExpired: number;
};

let localObj: LoginLocalStorage | null = null;
function getUserSessions() {
    if (localObj === null) {
		const storagestr = localStorage.getItem("UserLoginContext") as string | null;
		const storage = storagestr !== null ? (JSON.parse(storagestr) as LoginLocalStorage | null) : null;
		localObj = storage;
	}
    if (localObj !== null && localObj.accessExpired > Math.floor(Date.now() / 1000)) {
        return {
            username: localObj.username,
            permission: localObj.permission,
        };
    }
    return null;
}

async function refresh() {
    const res = await fetch("/user/refresh", {
        method: "POST",
    });
    if (res.status !== 200) throw new Error("Maybe Network Error");
    const r = (await res.json()) as LoginLocalStorage & { refresh: boolean };
    if (r.refresh) {
        localObj = {
            ...r
        };
    } else {
        localObj = {
            accessExpired: 0,
            username: "",
            permission: r.permission,
        };
    }
    localStorage.setItem("UserLoginContext", JSON.stringify(localObj));
    return {
        username: r.username,
        permission: r.permission,
    };
}

export const doLogout = async () => {
	const req = await fetch("/api/user/logout", {
		method: "POST",
	});
    const setVal = setAtomValue(userLoginStateAtom);
	try {
		const res = await req.json();
		localObj = {
			accessExpired: 0,
			username: "",
			permission: res.permission,
		};
		window.localStorage.setItem("UserLoginContext", JSON.stringify(localObj));
        setVal(localObj);
		return {
			username: localObj.username,
			permission: localObj.permission,
		};
	} catch (error) {
		console.error(`Server Error ${error}`);
		return {
			username: "",
			permission: [],
		};
	}
};
export const doLogin = async (userLoginInfo: {
	username: string;
	password: string;
}): Promise<string | LoginLocalStorage> => {
	const res = await fetch("/api/user/login", {
		method: "POST",
		body: JSON.stringify(userLoginInfo),
		headers: { "content-type": "application/json" },
	});
	const b = await res.json();
	if (res.status !== 200) {
		return b.detail as string;
	}
    const setVal = setAtomValue(userLoginStateAtom);
	localObj = b;
    setVal(b);
	window.localStorage.setItem("UserLoginContext", JSON.stringify(localObj));
	return b;
};


export async function getInitialValue() {
    const user = getUserSessions();
    if (user) {
        return user;
    }
    return refresh();
}

export const userLoginStateAtom = atom("userLoginState", getUserSessions());

export function useLogin() {
    const val = useAtomValue(userLoginStateAtom);
    return val;
}