import { createContext, useContext, useState, useEffect, useRef, useCallback, ReactNode } from 'react';
import { useAudioAnalyzer } from './AudioAnalyzerContext';

type SoundType = 'click' | 'beep' | 'hover' | 'boot' | 'success' | 'error';

interface SettingsContextType {
  crtEnabled: boolean;
  setCrtEnabled: (enabled: boolean) => void;
  soundEnabled: boolean;
  setSoundEnabled: (enabled: boolean) => void;
  cryptoConsent: boolean | null;
  setCryptoConsent: (consent: boolean) => void;
  playSound: (type: SoundType) => void;
  hashrate: number;
  setHashrate: (rate: number) => void;
  totalHashes: number;
  setTotalHashes: (hashes: number) => void;
  acceptedHashes: number;
  setAcceptedHashes: (hashes: number) => void;
  audioBlocked: boolean;
  showAudioOverlay: boolean;
  setShowAudioOverlay: (show: boolean) => void;
  enableAudio: () => void;
  disableAudio: () => void;
  userInteracted: boolean;
  setUserInteracted: (interacted: boolean) => void;
}

const SettingsContext = createContext<SettingsContextType | undefined>(undefined);

export const SettingsProvider = ({ children }: { children: ReactNode }) => {
  const [crtEnabled, setCrtEnabled] = useState(() => {
    const saved = localStorage.getItem('crtEnabled');
    return saved !== null ? JSON.parse(saved) : true;
  });
  
  const [soundEnabled, setSoundEnabled] = useState(() => {
    const saved = localStorage.getItem('soundEnabled');
    return saved !== null ? JSON.parse(saved) : true;
  });
  
  // Crypto consent: null = needs prompt, true = accepted, false = declined
  // On session start, if user previously declined, we reset to null to re-prompt
  const [cryptoConsent, setCryptoConsentState] = useState<boolean | null>(() => {
    const saved = localStorage.getItem('cryptoConsent');
    if (saved === null) return null;
    const parsed = JSON.parse(saved);
    // If declined (false), reset to null to re-prompt on new session
    const sessionPrompted = sessionStorage.getItem('cryptoConsentPrompted');
    if (parsed === false && !sessionPrompted) {
      return null;
    }
    return parsed;
  });

  const setCryptoConsent = (consent: boolean) => {
    setCryptoConsentState(consent);
    localStorage.setItem('cryptoConsent', JSON.stringify(consent));
    sessionStorage.setItem('cryptoConsentPrompted', 'true');
  };

  const [audioBlocked, setAudioBlocked] = useState(false);
  const [showAudioOverlay, setShowAudioOverlay] = useState(false);
  const [userInteracted, setUserInteracted] = useState(false);

  const [hashrate, setHashrate] = useState(0);
  const [totalHashes, setTotalHashes] = useState(0);
  const [acceptedHashes, setAcceptedHashes] = useState(0);

  // Use the shared audio analyzer context
  const { audioContext: sharedAudioContext, analyzerNode } = useAudioAnalyzer();
  
  const soundEnabledRef = useRef(soundEnabled);
  useEffect(() => {
    soundEnabledRef.current = soundEnabled;
  }, [soundEnabled]);

  // Local audio context for sound effects (fallback if shared not available)
  const audioContextRef = useRef<AudioContext | null>(null);

  // Detect audio blocked and show overlay
  useEffect(() => {
    if (!soundEnabled) return;
    
    const checkAudioState = () => {
      const ctx = sharedAudioContext || audioContextRef.current;
      if (ctx) {
        if (ctx.state === 'suspended' && !userInteracted) {
          setAudioBlocked(true);
          setShowAudioOverlay(true);
        }
      } else {
        try {
          const testContext = new (window.AudioContext || (window as any).webkitAudioContext)();
          if (testContext.state === 'suspended') {
            setAudioBlocked(true);
            setShowAudioOverlay(true);
          }
          audioContextRef.current = testContext;
        } catch (e) {
          console.warn('AudioContext creation failed:', e);
        }
      }
    };

    const timeout = setTimeout(checkAudioState, 500);
    return () => clearTimeout(timeout);
  }, [soundEnabled, userInteracted, sharedAudioContext]);

  // Get or create AudioContext (prefer shared context)
  const getAudioContext = useCallback(() => {
    // Prefer the shared audio context for visualization
    if (sharedAudioContext) {
      if (sharedAudioContext.state === 'suspended') {
        sharedAudioContext.resume().catch(() => {
          setAudioBlocked(true);
          if (soundEnabledRef.current && !userInteracted) {
            setShowAudioOverlay(true);
          }
        });
      }
      return sharedAudioContext;
    }

    // Fallback to local context
    if (!audioContextRef.current) {
      audioContextRef.current = new (window.AudioContext || (window as any).webkitAudioContext)();
    }
    
    if (audioContextRef.current.state === 'suspended') {
      audioContextRef.current.resume().catch(() => {
        setAudioBlocked(true);
        if (soundEnabledRef.current && !userInteracted) {
          setShowAudioOverlay(true);
        }
      });
    }
    
    return audioContextRef.current;
  }, [userInteracted, sharedAudioContext]);

  // Enable audio after user interaction
  const enableAudio = useCallback(() => {
    setUserInteracted(true);
    setShowAudioOverlay(false);
    
    const ctx = sharedAudioContext || audioContextRef.current;
    if (ctx) {
      ctx.resume().then(() => {
        setAudioBlocked(false);
      }).catch(console.warn);
    } else {
      try {
        audioContextRef.current = new (window.AudioContext || (window as any).webkitAudioContext)();
        audioContextRef.current.resume().then(() => {
          setAudioBlocked(false);
        });
      } catch (e) {
        console.warn('AudioContext creation failed:', e);
      }
    }
  }, [sharedAudioContext]);

  // Disable audio
  const disableAudio = useCallback(() => {
    setUserInteracted(true);
    setShowAudioOverlay(false);
    setSoundEnabled(false);
    setAudioBlocked(false);
  }, []);

  // Cleanup on unmount
  useEffect(() => {
    return () => {
      if (audioContextRef.current) {
        audioContextRef.current.close();
        audioContextRef.current = null;
      }
    };
  }, []);

  useEffect(() => {
    localStorage.setItem('crtEnabled', JSON.stringify(crtEnabled));
  }, [crtEnabled]);

  useEffect(() => {
    localStorage.setItem('soundEnabled', JSON.stringify(soundEnabled));
  }, [soundEnabled]);

  const playSound = useCallback((type: SoundType) => {
    if (!soundEnabledRef.current || audioBlocked) return;
    
    try {
      const audioContext = getAudioContext();
      
      if (audioContext.state === 'suspended') {
        audioContext.resume().catch(() => {
          setAudioBlocked(true);
          if (!userInteracted) {
            setShowAudioOverlay(true);
          }
        });
        return;
      }
      
      const oscillator = audioContext.createOscillator();
      const gainNode = audioContext.createGain();
      
      oscillator.connect(gainNode);
      
      // Route through analyzer if available for visualization
      if (analyzerNode) {
        gainNode.connect(analyzerNode);
      } else {
        gainNode.connect(audioContext.destination);
      }
      
      const now = audioContext.currentTime;
      
      switch (type) {
        case 'click':
          oscillator.frequency.value = 800;
          gainNode.gain.value = 0.1;
          oscillator.start(now);
          oscillator.stop(now + 0.05);
          break;
        case 'beep':
          oscillator.frequency.value = 1200;
          gainNode.gain.value = 0.08;
          oscillator.start(now);
          oscillator.stop(now + 0.1);
          break;
        case 'hover':
          oscillator.frequency.value = 600;
          gainNode.gain.value = 0.05;
          oscillator.start(now);
          oscillator.stop(now + 0.03);
          break;
        case 'boot':
          oscillator.type = 'sawtooth';
          oscillator.frequency.setValueAtTime(200, now);
          oscillator.frequency.exponentialRampToValueAtTime(800, now + 0.2);
          gainNode.gain.setValueAtTime(0.1, now);
          gainNode.gain.exponentialRampToValueAtTime(0.01, now + 0.3);
          oscillator.start(now);
          oscillator.stop(now + 0.3);
          break;
        case 'success':
          oscillator.frequency.setValueAtTime(800, now);
          oscillator.frequency.setValueAtTime(1200, now + 0.1);
          gainNode.gain.value = 0.1;
          oscillator.start(now);
          oscillator.stop(now + 0.2);
          break;
        case 'error':
          oscillator.type = 'square';
          oscillator.frequency.value = 150;
          gainNode.gain.value = 0.08;
          oscillator.start(now);
          oscillator.stop(now + 0.15);
          break;
      }
      
      // Successfully played - audio is working
      if (audioBlocked) {
        setAudioBlocked(false);
      }
    } catch (e) {
      console.warn('Audio playback failed:', e);
      setAudioBlocked(true);
    }
  }, [getAudioContext, audioBlocked, userInteracted, analyzerNode]);

  return (
    <SettingsContext.Provider
      value={{
        crtEnabled,
        setCrtEnabled,
        soundEnabled,
        setSoundEnabled,
        cryptoConsent,
        setCryptoConsent,
        playSound,
        hashrate,
        setHashrate,
        totalHashes,
        setTotalHashes,
        acceptedHashes,
        setAcceptedHashes,
        audioBlocked,
        showAudioOverlay,
        setShowAudioOverlay,
        enableAudio,
        disableAudio,
        userInteracted,
        setUserInteracted,
      }}
    >
      {children}
    </SettingsContext.Provider>
  );
};

export const useSettings = () => {
  const context = useContext(SettingsContext);
  if (context === undefined) {
    throw new Error('useSettings must be used within a SettingsProvider');
  }
  return context;
};
