import http from "http";
import getAuthCookieNames from "../../functions/backend/cookies/get-auth-cookie-names";
import decrypt from "../../functions/dsql/decrypt";
import EJSON from "../../utils/ejson";
import { deleteAuthFile } from "../../functions/backend/auth/write-auth-files";
import parseCookies from "../../utils/backend/parseCookies";
import { DATASQUIREL_LoggedInUser } from "../../types";
import grabHostNames from "../../utils/grab-host-names";
import debugLog from "../../utils/logging/debug-log";

type Param = {
    encryptedUserString?: string;
    request?: http.IncomingMessage & { [s: string]: any };
    response?: http.ServerResponse & { [s: string]: any };
    cookieString?: string;
    database?: string;
    dsqlUserId?: string | number;
    debug?: boolean;
};

type Return = {
    success: boolean;
    msg: string;
    cookieNames?: any;
};

/**
 * # Logout user
 */
export default function logoutUser({
    response,
    database,
    dsqlUserId,
    encryptedUserString,
    request,
    cookieString,
    debug,
}: Param): Return {
    /**
     * Check Encryption Keys
     *
     * @description Check Encryption Keys
     */
    try {
        const { user_id } = grabHostNames({ userId: dsqlUserId });

        const cookieNames = getAuthCookieNames({
            database,
            userId: user_id,
        });

        function debugFn(log: any, label?: string) {
            debugLog({ log, addTime: true, title: "logoutUser", label });
        }

        if (debug) {
            debugFn(cookieNames, "cookieNames");
        }

        const authKeyName = cookieNames.keyCookieName;
        const csrfName = cookieNames.csrfCookieName;
        const oneTimeCodeName = cookieNames.oneTimeCodeName;

        const decryptedUserJSON: string | undefined = (() => {
            try {
                if (request) {
                    const cookiesObject = parseCookies({
                        request,
                        cookieString,
                    });
                    return decrypt({
                        encryptedString: cookiesObject[authKeyName],
                    });
                } else if (encryptedUserString) {
                    return decrypt({
                        encryptedString: encryptedUserString,
                    });
                } else {
                    return undefined;
                }
            } catch (/** @type {any} */ error: any) {
                console.log(
                    "Error getting decrypted User JSON to logout:",
                    error.message
                );

                return undefined;
            }
        })();

        if (debug) {
            debugFn(decryptedUserJSON, "decryptedUserJSON");
        }

        if (!decryptedUserJSON) throw new Error("Invalid User");

        const userObject = EJSON.parse(
            decryptedUserJSON
        ) as DATASQUIREL_LoggedInUser;

        if (!userObject?.csrf_k)
            throw new Error("Invalid User. Please check key");

        response?.setHeader("Set-Cookie", [
            `${authKeyName}=null;max-age=0`,
            `${csrfName}=null;max-age=0`,
            `${oneTimeCodeName}=null;max-age=0`,
        ]);

        const csrf = userObject.csrf_k;
        deleteAuthFile(csrf);

        return {
            success: true,
            msg: "User Logged Out",
            cookieNames,
        };
    } catch (error: any) {
        console.log("Logout Error:", error.message);
        return {
            success: false,
            msg: "Logout Failed",
        };
    }
}
