import React, { createContext, useContext, useState, useEffect, useRef } from 'react';

interface VaultContextType {
  isLocked: boolean;
  isAuthenticated: boolean;
  communityId: string | null;
  unlock: (key: Uint8Array, communityId: string) => void;
  lock: () => void;
  decrypt: (data: Uint8Array) => Promise<string>;
}

const VaultContext = createContext<VaultContextType | undefined>(undefined);

export const VaultProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const [isLocked, setIsLocked] = useState(true);
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  const [communityId, setCommunityId] = useState<string | null>(null);
  const workerRef = useRef<Worker | null>(null);

  useEffect(() => {
    // Initialize the worker
    workerRef.current = new Worker(new URL('../workers/crypto.worker.ts', import.meta.url), {
        type: 'module'
    });

    return () => {
      workerRef.current?.terminate();
    };
  }, []);

  const unlock = (key: Uint8Array, community: string) => {
    workerRef.current?.postMessage({ type: 'SET_KEY', payload: key });
    setIsLocked(false);
    setIsAuthenticated(true);
    setCommunityId(community);
  };

  const lock = () => {
    // We don't just set the state, we terminate and recreate the worker to clear the memory
    workerRef.current?.terminate();
    workerRef.current = new Worker(new URL('../workers/crypto.worker.ts', import.meta.url), {
        type: 'module'
    });
    setIsLocked(true);
    setIsAuthenticated(false);
    setCommunityId(null);
  };

  const decrypt = (data: Uint8Array): Promise<string> => {
    return new Promise((resolve, reject) => {
      if (isLocked) return reject('Vault is locked');

      const handleMessage = (e: MessageEvent) => {
        if (e.data.type === 'DECRYPTED') {
          workerRef.current?.removeEventListener('message', handleMessage);
          resolve(e.data.payload);
        } else if (e.data.type === 'ERROR') {
          workerRef.current?.removeEventListener('message', handleMessage);
          reject(e.data.message);
        }
      };

      workerRef.current?.addEventListener('message', handleMessage);
      workerRef.current?.postMessage({ type: 'DECRYPTED', payload: data });
    });
  };

  return (
    <VaultContext.Provider value={{ isLocked, isAuthenticated, communityId, unlock, lock, decrypt }}>
      {children}
    </VaultContext.Provider>
  );
};

export const useVault = () => {
  const context = useContext(VaultContext);
  if (!context) throw new Error('useVault must be used within a VaultProvider');
  return context;
};
