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

interface DeviceProviderContextValue {
    deviceId: string;
}

export const DeviceProviderContext =            createContext<DeviceProviderContextValue|null>(null);

interface DeviceProviderProps {
    children?: React.ReactNode;
}

export function DeviceProvider(props: DeviceProviderProps) {
    const [deviceId, setDeviceId] = useState<string>("");
    const {writeFile, readFile} = useFileStorage();

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

    const fetchDeviceId = async () => {
        const device = await readFile("device");
        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 = window.deviceId;
        const platform = window.deviceName;
        const salt = "rosetta-device-salt";

        try {
            const decoded = await decodeWithPassword(hwid + platform + salt, data);
            return decoded;
        } catch (e) {
            console.error("Failed to decode device data:", e);
            return null;
        }
    }

    const encodeDevice = async (data: string) => {
        const hwid = window.deviceId;
        const platform = window.deviceName;
        const salt = "rosetta-device-salt";

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

    return (
        <DeviceProviderContext.Provider value={{
            deviceId: deviceId
        }}>
            {props.children}
        </DeviceProviderContext.Provider>
    )
}