"use server";
import { redis } from "@/lib/redis";
import { functionRetrieveUserSelection } from "@/apifetchers/utils";
import { ClientRedisToken } from "@/types/mutual/context/validations";
import { AuthError } from "@/types/mutual/context/validations";

// Redis operation timeout (5 seconds)
const REDIS_TIMEOUT = 5000;

// Default values for Redis data
const defaultValues: ClientRedisToken = {
    online: {
        lastLogin: new Date(),
        lastLogout: new Date(),
        lastAction: new Date(),
        lastPage: "/dashboard",
        userType: "employee",
        lang: "tr",
        timezone: "GMT+3"
    },
    pageConfig: {
        mode: "light",
        textFont: 14,
        theme: "default"
    },
    menu: {
        selectionList: ["/dashboard"],
        activeSelection: "/dashboard"
    },
    header: {
        header: [],
        activeDomain: "",
        listOfDomains: [],
        connections: []
    },
    selection: {
        selectionList: [],
        activeSelection: {}
    },
    user: {
        uuid: "",
        avatar: "",
        email: "",
        phone_number: "",
        user_tag: "",
        password_expiry_begins: new Date().toISOString(),
        person: {
            uuid: "",
            firstname: "",
            surname: "",
            middle_name: "",
            sex_code: "",
            person_tag: "",
            country_code: "",
            birth_date: ""
        }
    },
    settings: {
        lastOnline: new Date(),
        token: ""
    },
    chatRoom: {
        linkList: []
    },
    notifications: {
        linkList: []
    },
    messages: {
        linkList: []
    }
};

/**
 * Gets the complete data from Redis with improved error handling and timeouts
 * @returns The complete Redis data or default values if there's an error
 */
const getCompleteFromRedis = async (): Promise<ClientRedisToken> => {
    try {
        let decrpytUserSelection;
        try { decrpytUserSelection = await functionRetrieveUserSelection() } catch (error) { return defaultValues }
        const redisKey = decrpytUserSelection?.redisKey;
        if (!redisKey) { return defaultValues }
        if (redisKey === "default") { return defaultValues }

        try {
            const timeoutPromise = new Promise<string | null>((_, reject) => {
                setTimeout(() => reject(new Error('Redis operation timed out')), REDIS_TIMEOUT);
            });
            const result = await Promise.race([redis.get(`${redisKey}`), timeoutPromise]);
            if (!result) { return defaultValues }
            try { const parsedResult = JSON.parse(result); return parsedResult } catch (parseError) { return defaultValues }
        } catch (redisError) { return defaultValues }
    } catch (error) { return defaultValues }
}

/**
 * Sets the complete data in Redis with improved error handling and timeouts
 * @param completeObject The complete data to set in Redis
 * @returns True if successful, false otherwise
 */
const setCompleteToRedis = async (completeObject: ClientRedisToken): Promise<boolean> => {
    try {
        if (!completeObject) { return false }
        let decrpytUserSelection;
        try { decrpytUserSelection = await functionRetrieveUserSelection() } catch (error) { return false }
        if (!decrpytUserSelection) { return false }
        const redisKey = decrpytUserSelection?.redisKey;
        if (!redisKey) { return false }
        try {
            const timeoutPromise = new Promise((_, reject) => { setTimeout(() => reject(new Error('Redis operation timed out')), REDIS_TIMEOUT) });
            await Promise.race([redis.set(redisKey, JSON.stringify(completeObject)), timeoutPromise]);
            return true;
        } catch (redisError) { return false }
    } catch (error) { return false }
}

/**
 * Sets new complete data in Redis with a specific key with improved error handling and timeouts
 * @param completeObject The complete data to set in Redis
 * @param redisKey The specific Redis key to use
 * @returns True if successful, false otherwise
 */
const setNewCompleteToRedis = async (completeObject: ClientRedisToken, redisKey: string): Promise<boolean> => {
    try {
        if (!redisKey) { return false }
        if (!completeObject) { return false }
        try {
            const timeoutPromise = new Promise((_, reject) => { setTimeout(() => reject(new Error('Redis operation timed out')), REDIS_TIMEOUT) });
            await Promise.race([redis.set(redisKey, JSON.stringify(completeObject)), timeoutPromise])
            return true;
        } catch (redisError) { return false }
    } catch (error) { return false }
}

export { getCompleteFromRedis, setCompleteToRedis, setNewCompleteToRedis };
