import {
  AppBridgeMessage,
  AppBridgeResponse,
  BridgeMessageType,
  DeviceInfo,
  ShareContent
} from '@/types';

class AppBridge {
  private static instance: AppBridge;
  private messageId = 0;
  private pendingCallbacks = new Map<string, (response: AppBridgeResponse) => void>();
  private responseListeners: Set<(response: AppBridgeResponse) => void> = new Set();

  private constructor() {
    this.setupMessageListener();
  }

  // 외부에서 네이티브 응답을 구독할 수 있도록 리스너 등록/해제 메서드 추가
  public addResponseListener(listener: (response: AppBridgeResponse) => void) {
    this.responseListeners.add(listener);
  }

  public removeResponseListener(listener: (response: AppBridgeResponse) => void) {
    this.responseListeners.delete(listener);
  }

  static getInstance(): AppBridge {
    if (!AppBridge.instance) {
      AppBridge.instance = new AppBridge();
    }
    return AppBridge.instance;
  }

  private setupMessageListener(): void {
    window.addEventListener('message', (event) => {
      try {
        const response: AppBridgeResponse & { callbackId?: string } = typeof event.data === 'string' ? JSON.parse(event.data) : event.data;
        console.log('response', response);
        if (response.callbackId && this.pendingCallbacks.has(response.callbackId)) {
          const callback = this.pendingCallbacks.get(response.callbackId);
          if (callback) {
            callback(response);
            this.pendingCallbacks.delete(response.callbackId);
          }
        }
        // 등록된 리스너들에게 모든 응답 전달
        this.responseListeners.forEach(listener => listener(response));
      } catch (error) {
        console.error('Failed to parse bridge message:', error);
      }
    });
  }

  private generateMessageId(): string {
    return `bridge_${++this.messageId}_${Date.now()}`;
  }

  private sendMessage<T>(type: BridgeMessageType, data?: unknown): Promise<T> {
    return new Promise((resolve, reject) => {
      const callbackId = this.generateMessageId();
      const message: AppBridgeMessage & { callbackId: string } = {
        type,
        data,
        callbackId
      };

      this.pendingCallbacks.set(callbackId, (response: AppBridgeResponse) => {
        if (response.success) {
          resolve(response.data);
        } else {
          reject(new Error(response.error || 'Bridge call failed'));
        }
      });

      // Android WebView 인터페이스
      if (window.AndroidBridge && window.AndroidBridge.postMessage) {
        console.log('Android postMessage', message);
        window.AndroidBridge.postMessage(JSON.stringify(message));
        return;
      }
      
      // iOS WKWebView 인터페이스
      if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.bridge) {
        console.log('iOS postMessage', message);
        window.webkit.messageHandlers.bridge.postMessage(message);
        return;
      }

      // 네이티브 환경이 아닌 경우 에러 발생
      setTimeout(() => {
        this.pendingCallbacks.delete(callbackId);
        reject(new Error('Native bridge not available'));
      }, 100);
    });
  }

  // 앱 정보 관련
  async getAppInfo(): Promise<{ version: string; buildNumber: string }> {
    return this.sendMessage(BridgeMessageType.GET_APP_INFO);
  }

  async getDeviceInfo(): Promise<DeviceInfo> {
    return this.sendMessage(BridgeMessageType.GET_DEVICE_INFO);
  }

  // 네비게이션 관련
  async navigateBack(): Promise<void> {
    return this.sendMessage(BridgeMessageType.NAVIGATE_BACK);
  }

  async navigateTo(path: string): Promise<void> {
    return this.sendMessage(BridgeMessageType.NAVIGATE_TO, { path });
  }

  async closeWebView(): Promise<void> {
    return this.sendMessage(BridgeMessageType.CLOSE_WEBVIEW);
  }

  // 알림 관련
  async showToast(message: string, duration: number = 3000): Promise<void> {
    return this.sendMessage(BridgeMessageType.SHOW_TOAST, { message, duration });
  }

  async showAlert(title: string, message: string): Promise<void> {
    return this.sendMessage(BridgeMessageType.SHOW_ALERT, { title, message });
  }

  async showConfirm(title: string, message: string): Promise<boolean> {
    return this.sendMessage(BridgeMessageType.SHOW_CONFIRM, { title, message });
  }

  // 저장소 관련
  async setStorage(key: string, value: unknown): Promise<void> {
    return this.sendMessage(BridgeMessageType.SET_STORAGE, { key, value: JSON.stringify(value) });
  }

  async getStorage<T>(key: string): Promise<T | null> {
    try {
      const result = await this.sendMessage<string>(BridgeMessageType.GET_STORAGE, { key });
      return result ? JSON.parse(result) : null;
    } catch {
      return null;
    }
  }

  async removeStorage(key: string): Promise<void> {
    return this.sendMessage(BridgeMessageType.REMOVE_STORAGE, { key });
  }

  // 공유 관련
  async shareContent(content: ShareContent): Promise<void> {
    return this.sendMessage(BridgeMessageType.SHARE_CONTENT, content);
  }

  async logout(): Promise<void> {
    return this.sendMessage(BridgeMessageType.LOGOUT);
  }

  // 언어 설정
  async setLanguage(language: string): Promise<void> {
    return this.sendMessage(BridgeMessageType.SET_LANGUAGE, { language });
  }

  async getLanguage(): Promise<string> {
    return this.sendMessage(BridgeMessageType.GET_LANGUAGE);
  }

  // 알림 카운트 업데이트
  async updateAlarmCount(count: number): Promise<void> {
    return this.sendMessage(BridgeMessageType.UPDATE_ALARM_COUNT, { count });
  }

  // 네이티브 환경 체크
  isNativeEnvironment(): boolean {
    return !!(
      (window.AndroidBridge && window.AndroidBridge.postMessage) ||
      (window.Android && window.Android.processMessage) ||
      (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.bridge)
    );
  }

  isAndroid(): boolean {
    return !!(
      (window.AndroidBridge && window.AndroidBridge.postMessage) ||
      (window.Android && window.Android.processMessage)
    );
  }

  isIOS(): boolean {
    return !!(window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.bridge);
  }

  // 에러 핸들링을 위한 래퍼 메소드들
  async safeCall<T>(
    bridgeMethod: () => Promise<T>,
    fallback?: T,
    onError?: (error: Error) => void
  ): Promise<T | undefined> {
    try {
      return await bridgeMethod();
    } catch (error) {
      console.error('Bridge call failed:', error);
      if (onError) {
        onError(error as Error);
      }
      return fallback;
    }
  }

  // 타임아웃을 가진 브리지 호출
  async callWithTimeout<T>(
    bridgeMethod: () => Promise<T>,
    timeout: number = 5000
  ): Promise<T> {
    return Promise.race([
      bridgeMethod(),
      new Promise<never>((_, reject) => 
        setTimeout(() => reject(new Error('Bridge call timeout')), timeout)
      )
    ]);
  }
}

// 글로벌 타입 선언 확장
declare global {
  interface Window {
    AndroidBridge?: {
      postMessage: (message: string) => void;
    };
    Android?: {
      processMessage: (message: string) => void;
    };
    webkit?: {
      messageHandlers?: {
        bridge?: {
          postMessage: (message: unknown) => void;
        };
      };
    };
  }
}

export const appBridge = AppBridge.getInstance();
export default appBridge;