/**
 * FCM (Firebase Cloud Messaging) Push Notification Handler
 * Capacitor 앱에서만 동작, 웹 브라우저에서는 무시됨
 *
 * 포팅 원본: mng/public/js/fcm.js
 *
 * Payload data 스키마:
 * - type: 알림 타입 (invoice_failed, order_completed 등)
 * - url: 클릭 시 이동 URL
 * - sound_key: 사운드 파일 키 (sounds/{sound_key}.wav)
 *
 * NOTE: window.Capacitor 전역 객체 사용 (Capacitor 앱이 런타임에 주입)
 */

// ===== TypeScript 타입 정의 (window.Capacitor) =====

interface CapacitorGlobal {
  getPlatform: () => 'ios' | 'android' | 'web';
  isPluginAvailable: (name: string) => boolean;
  Plugins: {
    PushNotifications?: {
      removeAllListeners: () => Promise<void>;
      addListener: (event: string, callback: (data: unknown) => void) => void;
      requestPermissions: () => Promise<{ receive: string }>;
      register: () => Promise<void>;
    };
    App?: {
      addListener: (event: string, callback: (data: { isActive: boolean }) => void) => void;
    };
  };
}

declare global {
  interface Window {
    Capacitor?: CapacitorGlobal;
  }
}

// ===== 설정 =====

const CONFIG = {
  // Next.js 프록시 경로 (HttpOnly 쿠키 자동 포함)
  // NOTE: /api/proxy 사용 - 프록시가 자동으로 /api/v1/ 추가함
  proxyBasePath: '/api/proxy',
  fcmTokenKey: 'fcm_token',
  soundBasePath: '/sounds/',
  defaultSound: 'default',
};

// ===== 타입 정의 =====

export interface PushNotificationData {
  type?: string;
  url?: string;
  sound_key?: string;
  [key: string]: unknown;
}

export interface FCMNotification {
  title?: string;
  body?: string;
  data?: PushNotificationData;
}

export type ForegroundNotificationHandler = (notification: FCMNotification) => void;

// ===== 상태 =====

let isAppForeground = true;
let isInitialized = false;

// ===== 유틸리티 함수 =====

/**
 * Capacitor 네이티브 환경인지 확인
 */
export function isCapacitorNative(): boolean {
  if (typeof window === 'undefined') return false;
  const platform = window.Capacitor?.getPlatform?.();
  return platform === 'ios' || platform === 'android';
}

/**
 * 현재 플랫폼 반환
 */
export function getDevicePlatform(): 'ios' | 'android' | 'web' {
  if (typeof window === 'undefined') return 'web';
  const platform = window.Capacitor?.getPlatform?.();
  if (platform === 'ios' || platform === 'android') return platform;
  return 'web';
}

/**
 * 디바이스 이름 반환 (User-Agent 기반)
 */
function getDeviceName(): string | null {
  if (typeof navigator === 'undefined') return null;
  return navigator.userAgent?.substring(0, 100) || null;
}

/**
 * 앱 버전 반환
 */
function getAppVersion(): string | null {
  return process.env.NEXT_PUBLIC_APP_VERSION || null;
}

// ===== FCM 핵심 함수 =====

/**
 * FCM 초기화 (Capacitor 네이티브 환경에서만 동작)
 *
 * @param onForegroundNotification 포그라운드 알림 핸들러 (sonner toast 등)
 * @returns 초기화 성공 여부
 */
export async function initializeFCM(
  onForegroundNotification?: ForegroundNotificationHandler
): Promise<boolean> {
  // 브라우저 환경 체크
  if (typeof window === 'undefined') {
    return false;
  }

  // Capacitor 전역 객체 체크
  if (!window.Capacitor) {
    return false;
  }

  // 네이티브 환경 체크
  const platform = window.Capacitor.getPlatform();
  if (platform !== 'ios' && platform !== 'android') {
    return false;
  }

  // PushNotifications 플러그인 체크
  const PushNotifications = window.Capacitor.Plugins?.PushNotifications;
  if (!PushNotifications) {
    return false;
  }

  if (isInitialized) {
    return true;
  }

  try {
    // 앱 상태 리스너 (포그라운드/백그라운드)
    const App = window.Capacitor.Plugins?.App;
    if (App) {
      App.addListener('appStateChange', ({ isActive }) => {
        isAppForeground = isActive;
      });
    }

    // 기존 리스너 제거
    await PushNotifications.removeAllListeners();

    // 리스너 등록 (register() 호출 전에 등록해야 함)
    PushNotifications.addListener('registration', async (tokenData: unknown) => {
      const token = (tokenData as { value: string })?.value;
      await handleTokenRegistration(token);
    });

    PushNotifications.addListener('registrationError', (err: unknown) => {
      console.error('[FCM] Registration error:', err);
    });

    PushNotifications.addListener('pushNotificationReceived', (notification: unknown) => {

      const notif = notification as { title?: string; body?: string; data?: PushNotificationData };
      const fcmNotification: FCMNotification = {
        title: notif.title,
        body: notif.body,
        data: notif.data,
      };

      // 포그라운드 알림 콜백 호출
      if (onForegroundNotification) {
        onForegroundNotification(fcmNotification);
      }

      // 사운드 재생
      handleForegroundSound(notif.data?.sound_key);
    });

    PushNotifications.addListener('pushNotificationActionPerformed', (action: unknown) => {
      const actionData = action as { notification?: { data?: { url?: string } } };
      const url = actionData.notification?.data?.url;
      if (url && typeof url === 'string') {
        // URL 이동 (router.push 대신 window.location.href 사용 - 확실한 이동)
        window.location.href = url;
      }
    });

    // 권한 요청
    const perm = await PushNotifications.requestPermissions();

    if (perm.receive !== 'granted') {
      return false;
    }

    // 토큰 발급 요청 (registration 이벤트 트리거)
    await PushNotifications.register();

    isInitialized = true;
    return true;

  } catch (error) {
    console.error('[FCM] Initialization error:', error);
    return false;
  }
}

/**
 * 토큰 등록 처리
 */
async function handleTokenRegistration(newToken: string): Promise<void> {
  if (typeof window === 'undefined') return;

  const oldToken = sessionStorage.getItem(CONFIG.fcmTokenKey);

  if (oldToken === newToken) {
    return;
  }

  const success = await registerTokenToServer(newToken);

  if (success) {
    sessionStorage.setItem(CONFIG.fcmTokenKey, newToken);
  }
}

/**
 * 서버에 토큰 등록 (Next.js 프록시 사용)
 */
async function registerTokenToServer(token: string): Promise<boolean> {
  try {
    // Next.js 프록시 경로 사용 (HttpOnly 쿠키 자동 포함)
    const response = await fetch(`${CONFIG.proxyBasePath}/push/register-token`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
      },
      credentials: 'include', // 쿠키 포함
      body: JSON.stringify({
        token,
        platform: getDevicePlatform(),
        device_name: getDeviceName(),
        app_version: getAppVersion(),
      }),
    });

    if (response.ok) {
      return true;
    }

    console.error('[FCM] Token registration failed:', response.status);
    return false;

  } catch (error) {
    console.error('[FCM] Failed to send token:', error);
    return false;
  }
}

/**
 * 토큰 해제 (로그아웃 시 호출)
 */
export async function unregisterFCMToken(): Promise<boolean> {
  if (typeof window === 'undefined') return true;

  const token = sessionStorage.getItem(CONFIG.fcmTokenKey);
  if (!token) return true;

  try {
    // Next.js 프록시 경로 사용
    await fetch(`${CONFIG.proxyBasePath}/push/unregister-token`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
      },
      credentials: 'include',
      body: JSON.stringify({ token }),
    });
  } catch (__e) {
    console.warn('[FCM] Unregister failed, clearing local token');
  }

  sessionStorage.removeItem(CONFIG.fcmTokenKey);
  isInitialized = false;
  return true;
}

/**
 * 포그라운드 사운드 재생
 */
function handleForegroundSound(soundKey?: string): void {
  if (!isAppForeground) return;
  if (!soundKey) return;

  try {
    const soundPath = `${CONFIG.soundBasePath}${soundKey}.wav`;
    const audio = new Audio(soundPath);

    audio.volume = 0.5;
    audio.play().catch((err) => {
      console.warn('[FCM] Sound play failed, trying default:', err.message);
      // 기본 사운드 시도
      if (soundKey !== CONFIG.defaultSound) {
        const defaultAudio = new Audio(`${CONFIG.soundBasePath}${CONFIG.defaultSound}.wav`);
        defaultAudio.volume = 0.5;
        defaultAudio.play().catch(() => {});
      }
    });
  } catch (err) {
    console.warn('[FCM] Sound error:', err);
  }
}

/**
 * FCM 재초기화 (테스트/디버그용)
 */
export async function reinitializeFCM(
  onForegroundNotification?: ForegroundNotificationHandler
): Promise<boolean> {
  isInitialized = false;
  return initializeFCM(onForegroundNotification);
}

/**
 * 테스트용 사운드 재생
 */
export function testPlaySound(soundKey: string): void {
  handleForegroundSound(soundKey);
}

// ===== 알림 타입별 스타일 =====

export type ToastType = 'info' | 'success' | 'warning' | 'error';

/**
 * 알림 타입에 따른 토스트 스타일 결정
 */
export function getToastTypeByNotificationType(type?: string): ToastType {
  if (!type) return 'info';

  const typeMap: Record<string, ToastType> = {
    // 긴급/에러
    invoice_failed: 'error',
    payment_failed: 'error',
    order_cancelled: 'error',

    // 경고
    approval_required: 'warning',
    stock_low: 'warning',

    // 성공
    order_completed: 'success',
    payment_completed: 'success',
    approval_approved: 'success',

    // 기본
    default: 'info',
  };

  return typeMap[type] || 'info';
}