import { AccessTokens } from './mongodb';
import { createHash } from 'crypto';
import { ObjectId } from 'mongodb';
import DBAccessToken from '../../types/db/DBAccessToken';
import AccessToken from '../../types/AccessToken';
import locationManager from '../classes/managers/LocationManager';

export const createAccessToken = async (accessToken: AccessToken) => {
    const formatted: DBAccessToken = {
        _id: new ObjectId(),
        type: accessToken.type,
        user: accessToken.user?.id ?? new ObjectId(0),
        entropy: accessToken.entropy,
        createdAt: accessToken.createdAt,
        expiresAt: accessToken.expiresAt ?? new Date(accessToken.createdAt.getTime() + 86400000),
        createdFrom: accessToken.createdFrom
    }

    const newAccessToken = await (await AccessTokens()).insertOne(formatted);
    return newAccessToken;
}

export const getAccessToken = async (accessToken: string) => {
    if(accessToken.split(".").length !== 4) return null;
    
    const type = accessToken.split(".")[0];
    const createdAt = new Date(Number(Buffer.from(accessToken.split(".")[1], 'base64url').toString()));
    const user = new ObjectId(Buffer.from(accessToken.split(".")[2], 'base64url').toString());
    const random = accessToken.split(".")[3];
    const entropy = createHash("sha256").update(random).digest("hex");

    const accessTokens = await AccessTokens();
    return accessTokens.findOne({ $and: [
        { type },
        { createdAt },
        { user },
        { entropy }
    ] }) as Promise<DBAccessToken | null>;
}

export const getAllAccessTokens = async () => {
    const master: AccessToken = {
        type: "X",
        user: null,
        entropy: "b70972be3921e04a8d0c442f64c2c19a4ac01e886e8e5649916f9b88870fa6dd",
        createdAt: new Date(1698851542427),
        expiresAt: null,
        createdFrom: null
    }

    const accessTokens = await AccessTokens();
    const arrayOfTokens = await accessTokens.find({}).toArray() as DBAccessToken[];

    const arr = [master];

    for(const token of arrayOfTokens) {
        const user = locationManager.getUser(token.user) ?? null;

        const tokenObject: AccessToken = {
            type: token.type,
            user,
            entropy: token.entropy,
            createdAt: token.createdAt,
            expiresAt: token.expiresAt,
            createdFrom: token.createdFrom
        }

        arr.push(tokenObject);
    }

    return arr;
}