// Drop-in copy of the playmez-embed-react-native package. Prefer the package: npm install playmez-embed-react-native
/**
 * Playmez game for React Native and Expo. Needs `react-native-webview`
 * (npm i react-native-webview / npx expo install react-native-webview).
 *
 *   import { PlaymezGame } from "./PlaymezGame";
 *   <PlaymezGame launchUrl={launchUrl} onEvent={(e) => ...} onClose={() => navigation.goBack()} />
 *
 * `launchUrl` comes from YOUR backend, which calls POST /partner/launch with the API key.
 * Never put the key in the app bundle.
 *
 * Voice at shared tables: the WebView below grants media capture for the page it loads (the game
 * origin only) and plays inline media; add RECORD_AUDIO (Android) / NSMicrophoneUsageDescription
 * (iOS) to your app. Only needed when Playmez has switched voice on for you.
 */
import { useCallback } from "react";
import { StyleSheet, type StyleProp, type ViewStyle } from "react-native";
import { WebView, type WebViewMessageEvent } from "react-native-webview";

export type PlaymezEvent =
  | { source: "spinline"; type: "ready"; game: string }
  | { source: "spinline"; type: "result"; game: string; won: boolean; net: number }
  | { source: "spinline"; type: "close" }
  | { source: "spinline"; type: "error"; code: string; message: string }
  | { source: "spinline"; type: "resize"; height: number };

export interface PlaymezGameProps {
  launchUrl: string;
  onEvent?: (event: PlaymezEvent) => void;
  /** The player tapped Leave or Close: pop the screen or hide the view. */
  onClose?: () => void;
  style?: StyleProp<ViewStyle>;
  /** Let the game use the microphone for voice at shared tables. Default true. */
  allowMicrophone?: boolean;
}

/** Parses one WebView message into a Playmez event, or null for anything else. */
export function parseSpinlineMessage(raw: string): PlaymezEvent | null {
  let data: unknown;
  try {
    data = JSON.parse(raw);
  } catch {
    return null;
  }
  if (!data || typeof data !== "object") return null;
  const d = data as { source?: unknown; type?: unknown };
  return d.source === "spinline" && typeof d.type === "string" ? (data as PlaymezEvent) : null;
}

export function PlaymezGame({ launchUrl, onEvent, onClose, style, allowMicrophone = true }: PlaymezGameProps) {
  const onMessage = useCallback(
    (e: WebViewMessageEvent) => {
      const event = parseSpinlineMessage(e.nativeEvent.data);
      if (!event) return;
      onEvent?.(event);
      if (event.type === "close") onClose?.();
    },
    [onEvent, onClose],
  );

  return (
    <WebView
      source={{ uri: launchUrl }}
      onMessage={onMessage}
      javaScriptEnabled
      domStorageEnabled
      allowsInlineMediaPlayback
      mediaPlaybackRequiresUserAction={false}
      mediaCapturePermissionGrantType={allowMicrophone ? "grant" : "deny"}
      setSupportMultipleWindows={false}
      allowsBackForwardNavigationGestures={false}
      bounces={false}
      style={[styles.web, style]}
    />
  );
}

const styles = StyleSheet.create({
  web: { flex: 1, backgroundColor: "#0b0f1a" },
});
