import { decodeWithPassword, encodeWithPassword } from "@/app/workers/crypto/crypto";
import { useFileStorage } from "@/app/hooks/useFileStorage";
import { generateRandomKey } from "@/app/utils/utils";
import { createContext, useEffect, useState } from "react";
import { useCore } from "@/app/hooks/useCore";

interface SystemProviderContextValue {
    id: string;
    name: string;
    os: string;
}

export const SystemProviderContext = createContext<SystemProviderContextValue|null>(null);

export interface SystemProviderProps {
    children?: React.ReactNode;
}

/**
 * Предоставляет информацию о системе и обезличенный
 * идентификатор устройства.
 */
export function SystemProvider(props: SystemProviderProps) {
    const [deviceId, setDeviceId] = useState<string>("");
    const [deviceName, setDeviceName] = useState<string>("");
    const [deviceOs, setDeviceOs] = useState<string>("");
    const {writeFile, readFile} = useFileStorage();
    const { getDeviceId, getDeviceName, getPlatform } = useCore();

    useEffect(() => {
        fetchDeviceId();
    }, []);

    const fetchDeviceId = async () => {
        const device = await readFile("device");
        const name = await getDeviceName();
        const platform = await getPlatform();
        setDeviceName(name);
        setDeviceOs(platform);
        if(device){
            const decoded = await decodeDevice(Buffer.from(device).toString('utf-8'));
            if(decoded){
                setDeviceId(decoded);
                return;
            }
        }
        await createDeviceId();
    }

    const createDeviceId = async () => {
        const newDevice = generateRandomKey(128);
        const encoded = await encodeDevice(newDevice);
        await writeFile("device", encoded);
        setDeviceId(newDevice);
    }
    
    const decodeDevice = async (data: string) => {
        const hwid = await getDeviceId();
        const deviceName = await getDeviceName();
        const salt = "rosetta-device-salt";
        try {
            const decoded = await decodeWithPassword(hwid + deviceName + salt, data);
            return decoded;
        } catch (e) {
            console.error("Failed to decode device data:", e);
            return null;
        }
    }

    const encodeDevice = async (data: string) => {
        const hwid = await getDeviceId();
        const deviceName = await getDeviceName();
        const salt = "rosetta-device-salt";

        try {
            const encoded = await encodeWithPassword(hwid + deviceName + salt, data);
            return encoded;
        } catch (e) {
            console.error("Failed to encode device data:", e);
            return null;
        }
    }    

    return (
        <SystemProviderContext.Provider value={{
            id: deviceId,
            name: deviceName || "Unknown Device",
            os: deviceOs || "Unknown OS"
        }}>
            {props.children}
        </SystemProviderContext.Provider>
    );
}