// Public app-info fetcher + semver compare. Used by the in-app update popup
// and the Account "Help & About" card. No auth required — works for guests too.

const BASE =
  import.meta.env.VITE_BACKEND_URL ||
  import.meta.env.REACT_APP_BACKEND_URL ||
  "";

export type AppUpdateInfo = {
  enabled: boolean;
  latest_version: string;
  min_supported_version: string;
  apk_url: string;
  play_url: string;
  changelog: string;
  /** Delay (in seconds) before the update popup appears. Admin-controlled
   * so the admin can log in before a forced update locks them out. */
  popup_delay_seconds: number;
};

export type AppCreatorInfo = {
  name: string;
  role: string;
  avatar_url: string;
  bio: string;
};

export type AppSupportInfo = {
  whatsapp_number: string;
  whatsapp_message: string;
  email: string;
};

export type AppFlags = {
  player_notice_enabled?: boolean;
  external_player_enabled?: boolean;
  inline_preview_enabled?: boolean;
  proxy_enabled?: boolean;
  /**
   * Server-controlled kill-switch for FCM push notifications.
   *
   * Default: FALSE. Devices MUST refuse to call
   * `PushNotifications.register()` while this is off — calling Firebase
   * Messaging in an APK that was built before `google-services.json`
   * was bundled crashes the WebView natively (the v2.1.0 silent
   * post-login crash on ROG 8 Pro / Android 14-15).
   *
   * Admin flips this ON only after distributing an APK that contains
   * the firebase config.
   */
  push_enabled?: boolean;
};

export type AppTVBannerInfo = {
  /** Master enable flag for Smart-TV "house ad" banner. */
  enabled: boolean;
  /** Which payload to render: an `<img>` wrapped in `<a>`, or raw HTML. */
  type: "image" | "html";
  /** Raw HTML snippet (used when `type === "html"`). */
  html: string;
  /** Image source URL (used when `type === "image"`). */
  image_url: string;
  /** Optional click URL — when set, the image is wrapped in `<a target="_blank">`. */
  click_url: string;
};

export type AppInfo = {
  update: AppUpdateInfo;
  creator: AppCreatorInfo;
  support: AppSupportInfo;
  /** Admin-controlled feature flags. Mirrored from /playback-mode so the
   *  device has a second source if any deployment is stale. */
  flags?: AppFlags;
  privacy_policy_text: string;
  /** Admin-editable Terms &amp; Conditions text. Plain text or markdown,
   *  surfaced by the About menu modal on the Account page. */
  terms_policy_text?: string;
  /** FEATURE (2026-01) — Smart-TV custom banner config. Only rendered
   *  by the React app when `isSmartTV()` returns true AND
   *  `tv_banner.enabled` is true. */
  tv_banner?: AppTVBannerInfo;
};

export const APP_VERSION: string =
  typeof __APP_VERSION__ !== "undefined" ? __APP_VERSION__ : "1.0.0";

/**
 * Resolve the *real* installed version of the app at runtime.
 *
 * - On the Android APK / iOS bundle (Capacitor), reads `App.getInfo().version`,
 *   which mirrors `android/app/build.gradle`'s `versionName`. This is the
 *   value the user actually sees in Settings → Apps.
 * - On the web preview (no Capacitor available), falls back to the
 *   compile-time `__APP_VERSION__` baked from `package.json`.
 *
 * Means the admin only has to bump `versionName` in `build.gradle` (and
 * rebuild the APK) — they never need to also edit the React bundle. After
 * a user installs the new APK, the popup automatically stops showing.
 */
export async function resolveInstalledVersion(): Promise<string> {
  // Cheap web/preview short-circuit so we don't even try to dynamic-import
  // @capacitor/app in environments where Capacitor doesn't exist.
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const w = (typeof window !== "undefined" ? (window as any) : null);
  const isNative = !!(w && w.Capacitor && w.Capacitor.isNativePlatform &&
    w.Capacitor.isNativePlatform());
  if (!isNative) return APP_VERSION;
  try {
    const { App } = await import("@capacitor/app");
    const info = await App.getInfo();
    // info.version === build.gradle `versionName`
    const v = (info && info.version) ? String(info.version).trim() : "";
    return v || APP_VERSION;
  } catch {
    return APP_VERSION;
  }
}

export async function fetchAppInfo(): Promise<AppInfo> {
  const res = await fetch(`${BASE}/api/public/app-info`, {
    headers: { Accept: "application/json" },
  });
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return (await res.json()) as AppInfo;
}

/**
 * Compare two semver-ish strings. Returns:
 *   1  if a > b
 *  -1  if a < b
 *   0  if equal (or unparseable)
 *
 * Tolerates "1.2", "1.2.3", "1.2.3-beta" — strips suffixes after `-`.
 */
export function compareVersions(a: string, b: string): number {
  const norm = (v: string) =>
    (v || "0")
      .trim()
      .split("-")[0]
      .split(".")
      .map((p) => parseInt(p, 10) || 0);
  const pa = norm(a);
  const pb = norm(b);
  const n = Math.max(pa.length, pb.length);
  for (let i = 0; i < n; i++) {
    const x = pa[i] ?? 0;
    const y = pb[i] ?? 0;
    if (x > y) return 1;
    if (x < y) return -1;
  }
  return 0;
}

export function buildWhatsAppUrl(
  number: string,
  message: string,
): string | null {
  const digits = (number || "").replace(/[^\d]/g, "");
  if (!digits) return null;
  const text = encodeURIComponent(message || "");
  return `https://wa.me/${digits}${text ? `?text=${text}` : ""}`;
}
