'use client';

import { useEffect, useState, useCallback } from 'react';
import { ReminderSettings } from '@/lib/storage';

const LAST_NOTIFICATION_KEY = 'quittraq_last_notification_date';

export type NotificationPermission = 'default' | 'granted' | 'denied';

// Helper to convert VAPID key
function urlBase64ToUint8Array(base64String: string) {
  const padding = '='.repeat((4 - base64String.length % 4) % 4);
  const base64 = (base64String + padding)
    .replace(/-/g, '+')
    .replace(/_/g, '/');

  const rawData = window.atob(base64);
  const outputArray = new Uint8Array(rawData.length);

  for (let i = 0; i < rawData.length; ++i) {
    outputArray[i] = rawData.charCodeAt(i);
  }
  return outputArray;
}

export function useNotifications(reminderSettings: ReminderSettings) {
  const [permission, setPermission] = useState<NotificationPermission>('default');
  const [isSupported, setIsSupported] = useState(false);
  const [swRegistration, setSwRegistration] = useState<ServiceWorkerRegistration | null>(null);

  // Register Service Worker
  useEffect(() => {
    if (typeof window !== 'undefined' && 'serviceWorker' in navigator && 'PushManager' in window) {
      setIsSupported(true);
      setPermission(Notification.permission as NotificationPermission);

      navigator.serviceWorker.register('/sw.js')
        .then(registration => {
          console.log('Service Worker registered:', registration);
          setSwRegistration(registration);
        })
        .catch(error => {
          console.error('Service Worker registration failed:', error);
        });
    }
  }, []);

  const subscribeToPush = useCallback(async () => {
    try {
      const registration = await navigator.serviceWorker.ready;
      if (!registration) {
        throw new Error('Service Worker not ready');
      }

      const publicVapidKey = process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY;
      if (!publicVapidKey) {
        throw new Error('Missing VAPID key');
      }

      // 1. Ensure we have a subscription
      let subscription = await registration.pushManager.getSubscription();

      if (!subscription) {
        subscription = await registration.pushManager.subscribe({
          userVisibleOnly: true,
          applicationServerKey: urlBase64ToUint8Array(publicVapidKey)
        });
        console.log('New push notification subscribed');
      } else {
        console.log('Existing push subscription found, syncing with server...');
      }

      // 2. Refresh it on the backend (ALWAYS)
      const res = await fetch('/api/notifications/subscribe', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ subscription }),
      });

      if (!res.ok) {
        const data = await res.json() as { error?: string };
        throw new Error(data.error || 'Failed to sync subscription to server');
      }

      // Success
      console.log('Subscription synced with server');
    } catch (error) {
      console.error('Failed to subscribe:', error);
      throw error; // Propagate to caller
    }
  }, []);

  // Request notification permission
  const requestPermission = useCallback(async () => {
    if (!isSupported) return 'denied';

    try {
      const result = await Notification.requestPermission();
      setPermission(result as NotificationPermission);

      if (result === 'granted') {
        // Verify we can subscribe and save to backend
        await subscribeToPush();
      }
      return result;
    } catch (error) {
      console.error('Error requesting notification permission:', error);
      alert('Error enabling notifications: ' + (error instanceof Error ? error.message : 'Unknown error'));
      return 'denied';
    }
  }, [isSupported, subscribeToPush]);

  // Send a notification
  const sendNotification = useCallback(
    (title: string, options?: NotificationOptions) => {
      if (!isSupported || permission !== 'granted') return;

      try {
        const notification = new Notification(title, {
          icon: '/icon-192.png',
          badge: '/icon-192.png',
          ...options,
        });

        notification.onclick = () => {
          window.focus();
          notification.close();
        };

        return notification;
      } catch (error) {
        console.error('Error sending notification:', error);
      }
    },
    [isSupported, permission]
  );

  // Play a "bubble pop" sound using Web Audio API
  const playNotificationSound = useCallback(() => {
    try {
      const AudioContext = window.AudioContext || (window as any).webkitAudioContext;
      if (!AudioContext) return;

      const ctx = new AudioContext();
      const oscillator = ctx.createOscillator();
      const gainNode = ctx.createGain();

      oscillator.connect(gainNode);
      gainNode.connect(ctx.destination);

      // Bubble 'pop' effect: sine wave with rapid frequency drop
      oscillator.type = 'sine';
      oscillator.frequency.setValueAtTime(800, ctx.currentTime);
      oscillator.frequency.exponentialRampToValueAtTime(100, ctx.currentTime + 0.1);

      // Envelope: quick attack, quick decay
      gainNode.gain.setValueAtTime(0, ctx.currentTime);
      gainNode.gain.linearRampToValueAtTime(0.3, ctx.currentTime + 0.01);
      gainNode.gain.exponentialRampToValueAtTime(0.01, ctx.currentTime + 0.1);

      oscillator.start();
      oscillator.stop(ctx.currentTime + 0.15);
    } catch (e) {
      console.error('Error playing notification sound:', e);
    }
  }, []);

  // Track previous settings to detect changes
  const [prevSettings, setPrevSettings] = useState(reminderSettings);

  // If settings change, we record it
  useEffect(() => {
    if (JSON.stringify(prevSettings) !== JSON.stringify(reminderSettings)) {
      setPrevSettings(reminderSettings);
    }
  }, [reminderSettings, prevSettings]);

  return {
    isSupported,
    permission,
    requestPermission,
    sendNotification,
  };
}
