/**
 * Telegram Mini Apps SDK wrapper.
 *
 * The SDK script is loaded in index.html before the app mounts,
 * so `window.Telegram.WebApp` should be available synchronously.
 */

// Extend Window interface for Telegram SDK
declare global {
  interface Window {
    Telegram?: {
      WebApp: TelegramWebApp;
    };
  }
}

export interface TelegramWebApp {
  ready: () => void;
  expand: () => void;
  close: () => void;
  initData: string;
  initDataUnsafe: Record<string, unknown>;
  version: string;
  platform: string;
  colorScheme: 'light' | 'dark';
  themeParams: {
    bg_color?: string;
    text_color?: string;
    hint_color?: string;
    link_color?: string;
    button_color?: string;
    button_text_color?: string;
    secondary_bg_color?: string;
  };
  viewportHeight: number;
  viewportStableHeight: number;
  isExpanded: boolean;
  MainButton: {
    text: string;
    color: string;
    textColor: string;
    isVisible: boolean;
    isActive: boolean;
    show: () => void;
    hide: () => void;
    onClick: (cb: () => void) => void;
    offClick: (cb: () => void) => void;
    setText: (text: string) => void;
    enable: () => void;
    disable: () => void;
  };
  BackButton: {
    isVisible: boolean;
    show: () => void;
    hide: () => void;
    onClick: (cb: () => void) => void;
    offClick: (cb: () => void) => void;
  };
  HapticFeedback: {
    impactOccurred: (style: 'light' | 'medium' | 'heavy' | 'rigid' | 'soft') => void;
    notificationOccurred: (type: 'error' | 'success' | 'warning') => void;
    selectionChanged: () => void;
  };
  showPopup: (params: {
    title?: string;
    message: string;
    buttons?: Array<{ id?: string; type?: 'default' | 'ok' | 'close' | 'cancel' | 'destructive'; text?: string }>;
  }, cb?: (buttonId: string) => void) => void;
  requestWriteAccess: (cb?: (granted: boolean) => void) => void;
  onEvent: (event: string, cb: (...args: unknown[]) => void) => void;
  offEvent: (event: string, cb: (...args: unknown[]) => void) => void;
  sendData: (data: string) => void;
  setHeaderColor: (color: string) => void;
  setBackgroundColor: (color: string) => void;
}

/** Returns the Telegram WebApp instance, or null if not inside Telegram */
export function getTelegramWebApp(): TelegramWebApp | null {
  return window.Telegram?.WebApp ?? null;
}

/** Returns true if running inside a Telegram client */
export function isTelegram(): boolean {
  return getTelegramWebApp() !== null;
}

/** Initialize Telegram Mini App: signal readiness, expand viewport */
export function initTelegramApp(): void {
  const tg = getTelegramWebApp();
  if (!tg) {
    console.info('[Telegram] Not running inside Telegram, skipping init');
    return;
  }

  tg.ready();
  tg.expand();

  // Apply Telegram theme to CSS variables for UI components
  const theme = tg.themeParams;
  const root = document.documentElement;
  if (theme.bg_color) root.style.setProperty('--tg-bg', theme.bg_color);
  if (theme.text_color) root.style.setProperty('--tg-text', theme.text_color);
  if (theme.button_color) root.style.setProperty('--tg-button', theme.button_color);
  if (theme.button_text_color) root.style.setProperty('--tg-button-text', theme.button_text_color);
  if (theme.secondary_bg_color) root.style.setProperty('--tg-secondary-bg', theme.secondary_bg_color);

  console.info(`[Telegram] Initialized v${tg.version} on ${tg.platform}, scheme=${tg.colorScheme}`);
}

/** Get Telegram initData for authenticating API requests */
export function getTelegramInitData(): string {
  return getTelegramWebApp()?.initData ?? '';
}

/** Get the Telegram user ID from initDataUnsafe, or null if unavailable */
export function getTelegramUserId(): number | null {
  const tg = getTelegramWebApp();
  if (!tg) return null;
  const user = tg.initDataUnsafe?.user as { id?: number } | undefined;
  return user?.id ?? null;
}

/** Get viewport dimensions accounting for Telegram safe areas */
export function getViewport(): { width: number; height: number } {
  const tg = getTelegramWebApp();
  return {
    width: window.innerWidth,
    height: tg?.viewportStableHeight ?? window.innerHeight,
  };
}

// ---- Haptic Feedback ----

/** Trigger haptic impact feedback (combat hits, UI taps) */
export function hapticImpact(style: 'light' | 'medium' | 'heavy'): void {
  getTelegramWebApp()?.HapticFeedback.impactOccurred(style);
}

/** Trigger haptic notification feedback (success/error/warning events) */
export function hapticNotification(type: 'error' | 'success' | 'warning'): void {
  getTelegramWebApp()?.HapticFeedback.notificationOccurred(type);
}

// ---- Popup ----

/** Show a native Telegram popup dialog */
export function showPopup(
  title: string,
  message: string,
  buttons?: Array<{ id?: string; type?: 'default' | 'ok' | 'close' | 'cancel' | 'destructive'; text?: string }>,
): Promise<string> {
  return new Promise((resolve) => {
    const tg = getTelegramWebApp();
    if (!tg) {
      resolve('');
      return;
    }
    tg.showPopup({ title, message, buttons }, (buttonId) => {
      resolve(buttonId);
    });
  });
}

// ---- Write Access ----

/** Request write access permission from the user */
export function requestWriteAccess(): Promise<boolean> {
  return new Promise((resolve) => {
    const tg = getTelegramWebApp();
    if (!tg) {
      resolve(false);
      return;
    }
    tg.requestWriteAccess((granted) => {
      resolve(granted);
    });
  });
}

// ---- Theme Change Listener ----

/** Subscribe to Telegram theme changes and re-apply CSS variables */
export function onThemeChanged(cb?: () => void): () => void {
  const tg = getTelegramWebApp();
  if (!tg) return () => {};

  const handler = () => {
    const theme = tg.themeParams;
    const root = document.documentElement;
    if (theme.bg_color) root.style.setProperty('--tg-bg', theme.bg_color);
    if (theme.text_color) root.style.setProperty('--tg-text', theme.text_color);
    if (theme.button_color) root.style.setProperty('--tg-button', theme.button_color);
    if (theme.button_text_color) root.style.setProperty('--tg-button-text', theme.button_text_color);
    if (theme.secondary_bg_color) root.style.setProperty('--tg-secondary-bg', theme.secondary_bg_color);
    cb?.();
  };

  tg.onEvent('themeChanged', handler);

  // Return unsubscribe function
  return () => {
    tg.offEvent('themeChanged', handler);
  };
}
