"use client";

import { createContext, useContext, useEffect, useState } from "react";
import {
  init,
  mountMiniAppSync,
  mountThemeParamsSync,
  bindThemeParamsCssVars,
  mountViewport,
  bindViewportCssVars,
  unmountViewport,
} from "@telegram-apps/sdk-react";
import { fixSurfaceContrast, useTelegramTheme } from "@/hooks/use-telegram-theme";
import { applyAndroidPerformanceClass } from "@/lib/telegram-android-perf";
import { useAppStore } from "@/store/app-store";
import { getLang } from "@/i18n/messages";
import { useTranslation } from "@/i18n/use-translation";

const EVENT_CONFIG_LOADED = "dt-config-loaded";

export interface TelegramSdkContextValue {
  /** True after init() and sync mounts have run; safe to use backButton etc. */
  sdkReady: boolean;
}

const TelegramSdkContext = createContext<TelegramSdkContextValue>({
  sdkReady: false,
});

export function useTelegramSdkReady(): TelegramSdkContextValue {
  return useContext(TelegramSdkContext);
}

/**
 * Wraps the app with Telegram Mini App SDK initialization.
 * Calls init(acceptCustomStyles), mounts theme params (binds --tg-theme-* CSS vars),
 * mounts the mini app, then mounts viewport and binds viewport CSS vars
 * (--tg-viewport-stable-height, --tg-viewport-content-safe-area-inset-*, etc.).
 * Does not call ready() here — the app calls callMiniAppReadyOnce() from
 * lib/telegram-ready when the first visible screen has finished loading.
 * Theme is set before first paint by the inline script in layout.tsx (URL hash);
 * useTelegramTheme() in the app handles ongoing theme changes.
 * Syncs lang from window.__DT_LANG on mount and when config.js fires dt-config-loaded.
 */
/**
 * Live theme sync: provider-owned so every route (/, /admin, not-found, error) gets
 * data-theme and Mini App chrome color updates when Telegram theme changes.
 */
function ThemeSync() {
  useTelegramTheme();
  return null;
}

export function TelegramProvider({
  children,
}: {
  children: React.ReactNode;
}) {
  const [sdkReady, setSdkReady] = useState(false);
  const setLang = useAppStore((s) => s.setLang);
  const lang = useAppStore((s) => s.lang);
  const { t } = useTranslation();

  // Sync lang from backend config: on mount and when config.js has loaded (all routes, including admin).
  useEffect(() => {
    if (typeof window === "undefined") return;
    setLang(getLang());
    const onConfigLoaded = () => setLang(getLang());
    window.addEventListener(EVENT_CONFIG_LOADED, onConfigLoaded);
    return () => window.removeEventListener(EVENT_CONFIG_LOADED, onConfigLoaded);
  }, [setLang]);

  // Apply lang to document (title and html lang) so all routes including admin get correct title.
  useEffect(() => {
    if (typeof document === "undefined") return;
    document.documentElement.lang = lang;
    document.title = t("app.title");
  }, [lang, t]);

  useEffect(() => {
    const cleanup = init({ acceptCustomStyles: true });

    if (mountThemeParamsSync.isAvailable()) {
      mountThemeParamsSync();
    }
    if (bindThemeParamsCssVars.isAvailable()) {
      bindThemeParamsCssVars();
    }
    fixSurfaceContrast();
    void document.documentElement.offsetHeight;

    if (mountMiniAppSync.isAvailable()) {
      mountMiniAppSync();
    }

    applyAndroidPerformanceClass();

    setSdkReady(true);

    let unbindViewportCssVars: (() => void) | undefined;
    if (mountViewport.isAvailable()) {
      mountViewport()
        .then(() => {
          if (bindViewportCssVars.isAvailable()) {
            unbindViewportCssVars = bindViewportCssVars();
          }
        })
        .catch(() => {
          // Viewport not supported (e.g. not in Mini App); ignore.
        });
    }

    return () => {
      setSdkReady(false);
      unbindViewportCssVars?.();
      unmountViewport();
      cleanup();
    };
  }, []);

  return (
    <TelegramSdkContext.Provider value={{ sdkReady }}>
      <ThemeSync />
      {children}
    </TelegramSdkContext.Provider>
  );
}
