/**
 * Web Push 알림 유틸리티
 * Service Worker 등록 및 Push 구독 관리
 * 
 * ⚠️ 주의: Service Worker와 Web Push는 HTTPS 또는 localhost에서만 작동합니다!
 * HTTP 환경에서는 브라우저 알림만 사용하세요.
 */

// VAPID 공개 키 (백엔드에서 생성)
// 주의: 이 키는 백엔드 application.yml의 push.vapid.public-key와 동일해야 합니다!
const VAPID_PUBLIC_KEY = 'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4xZ0NOe_lJmuwRmNvEy8sokT3IqDxQiKBOx8YRJfw3fbURO36jPl0WC-SD9ZKbgldcnfUIYJHHOdCmanShM90g';

/**
 * HTTPS 환경 확인
 * Service Worker는 HTTPS 또는 localhost에서만 작동
 */
export const isSecureContext = (): boolean => {
  // HTTPS 또는 localhost 확인
  return window.isSecureContext || 
         window.location.protocol === 'https:' || 
         window.location.hostname === 'localhost' ||
         window.location.hostname === '127.0.0.1';
};

/**
 * PWA Web Push 지원 확인
 */
export const isPWAPushSupported = (): boolean => {
  return isSecureContext() && 'serviceWorker' in navigator && 'PushManager' in window;
};

/**
 * Service Worker 등록
 * ⚠️ HTTPS 또는 localhost에서만 작동
 */
export const registerServiceWorker = async (): Promise<ServiceWorkerRegistration | null> => {
  if (!isSecureContext()) {
    console.warn('[Push] ⚠️ HTTP 환경에서는 Service Worker가 작동하지 않습니다.');
    console.warn('[Push] HTTPS를 사용하거나 localhost에서 실행하세요.');
    console.warn('[Push] 현재는 브라우저 알림만 사용됩니다.');
    return null;
  }

  if (!('serviceWorker' in navigator)) {
    console.warn('[Push] Service Worker not supported in this browser');
    return null;
  }

  try {
    const registration = await navigator.serviceWorker.register('/service-worker.js', {
      scope: '/',
    });
    
    console.log('[Push] ✅ Service Worker registered:', registration);
    
    // Wait for the service worker to be ready
    await navigator.serviceWorker.ready;
    console.log('[Push] ✅ Service Worker ready');
    
    return registration;
  } catch (error) {
    console.error('[Push] ❌ Service Worker registration failed:', error);
    return null;
  }
};

/**
 * 알림 권한 요청
 */
export const requestNotificationPermission = async (): Promise<NotificationPermission> => {
  if (!('Notification' in window)) {
    console.warn('Notifications not supported in this browser');
    return 'denied';
  }

  if (Notification.permission === 'granted') {
    return 'granted';
  }

  if (Notification.permission === 'denied') {
    return 'denied';
  }

  const permission = await Notification.requestPermission();
  console.log('[Push] Notification permission:', permission);
  return permission;
};

/**
 * Base64를 Uint8Array로 변환 (VAPID 키 변환용)
 */
const urlBase64ToUint8Array = (base64String: string): Uint8Array => {
  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;
};

/**
 * Push 구독 생성
 */
export const subscribeToPush = async (): Promise<PushSubscription | null> => {
  try {
    // Service Worker 등록 확인
    const registration = await navigator.serviceWorker.ready;
    
    // 기존 구독 확인
    let subscription = await registration.pushManager.getSubscription();
    
    if (subscription) {
      console.log('[Push] Already subscribed:', subscription);
      return subscription;
    }

    // 알림 권한 요청
    const permission = await requestNotificationPermission();
    if (permission !== 'granted') {
      console.warn('[Push] Notification permission not granted');
      return null;
    }

    // 새 구독 생성
    subscription = await registration.pushManager.subscribe({
      userVisibleOnly: true,
      applicationServerKey: urlBase64ToUint8Array(VAPID_PUBLIC_KEY),
    });

    console.log('[Push] New subscription created:', subscription);
    return subscription;
  } catch (error) {
    console.error('[Push] Failed to subscribe:', error);
    return null;
  }
};

/**
 * Push 구독 해제
 */
export const unsubscribeFromPush = async (): Promise<boolean> => {
  try {
    const registration = await navigator.serviceWorker.ready;
    const subscription = await registration.pushManager.getSubscription();
    
    if (!subscription) {
      console.log('[Push] No subscription to unsubscribe');
      return true;
    }

    const result = await subscription.unsubscribe();
    console.log('[Push] Unsubscribed:', result);
    return result;
  } catch (error) {
    console.error('[Push] Failed to unsubscribe:', error);
    return false;
  }
};

/**
 * 현재 구독 상태 확인
 */
export const getSubscription = async (): Promise<PushSubscription | null> => {
  try {
    if (!('serviceWorker' in navigator)) {
      return null;
    }
    
    const registration = await navigator.serviceWorker.ready;
    const subscription = await registration.pushManager.getSubscription();
    return subscription;
  } catch (error) {
    console.error('[Push] Failed to get subscription:', error);
    return null;
  }
};

/**
 * 구독 정보를 서버로 전송
 */
export const sendSubscriptionToServer = async (
  subscription: PushSubscription,
  endpoint: string = '/api/user/settings/push-subscription'
): Promise<boolean> => {
  try {
    const token = localStorage.getItem('accessToken');
    if (!token) {
      console.warn('[Push] No access token found');
      return false;
    }

    const response = await fetch(endpoint, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${token}`,
      },
      body: JSON.stringify({
        subscription: subscription.toJSON(),
      }),
    });

    if (!response.ok) {
      throw new Error(`Failed to send subscription: ${response.statusText}`);
    }

    console.log('[Push] Subscription sent to server');
    return true;
  } catch (error) {
    console.error('[Push] Failed to send subscription to server:', error);
    return false;
  }
};

/**
 * 구독 삭제를 서버에 알림
 */
export const deleteSubscriptionFromServer = async (
  endpoint: string = '/api/user/settings/push-subscription'
): Promise<boolean> => {
  try {
    const token = localStorage.getItem('accessToken');
    if (!token) {
      console.warn('[Push] No access token found');
      return false;
    }

    const response = await fetch(endpoint, {
      method: 'DELETE',
      headers: {
        'Authorization': `Bearer ${token}`,
      },
    });

    if (!response.ok) {
      throw new Error(`Failed to delete subscription: ${response.statusText}`);
    }

    console.log('[Push] Subscription deleted from server');
    return true;
  } catch (error) {
    console.error('[Push] Failed to delete subscription from server:', error);
    return false;
  }
};

/**
 * PWA 초기화 (Service Worker 등록 + Push 구독)
 */
export const initializePWA = async (): Promise<void> => {
  console.log('[PWA] Initializing...');
  
  // Service Worker 등록
  const registration = await registerServiceWorker();
  if (!registration) {
    console.warn('[PWA] Service Worker registration failed');
    return;
  }

  // Push 구독은 사용자가 설정에서 수동으로 활성화
  console.log('[PWA] Initialized. Push subscription available in settings.');
};

/**
 * 테스트 알림 표시
 */
export const showTestNotification = async (): Promise<void> => {
  const permission = await requestNotificationPermission();
  
  if (permission !== 'granted') {
    alert('알림 권한이 거부되었습니다.');
    return;
  }

  const registration = await navigator.serviceWorker.ready;
  
  await registration.showNotification('테스트 알림', {
    body: '푸시 알림이 정상적으로 작동합니다! 🎉',
    icon: '/favicon.ico',
    badge: '/favicon.ico',
    vibrate: [200, 100, 200],
    tag: 'test-notification',
    requireInteraction: false,
  });
};

