import React, { ReactNode, useCallback, useEffect, useRef } from 'react';
import { useAtomValue, useSetAtom, useStore } from 'jotai';
import {
  CallEmbedContextProvider,
  CallEmbedRefContextProvider,
  useCallCloseEvent,
  useCallHangupEvent,
  useCallJoined,
  useCallThemeSync,
  useCallMemberSoundSync,
} from '../hooks/useCallEmbed';
import { callChatAtom, callEmbedAtom } from '../state/callEmbed';
import { CallEmbed } from '../plugins/call';
import { useSelectedRoom } from '../hooks/router/useSelectedRoom';
import { ScreenSize, useScreenSizeContext } from '../hooks/useScreenSize';
import { useAndroidCallForegroundSync } from '../hooks/useAndroidCallForegroundSync';

function CallUtils({ embed }: { embed: CallEmbed }) {
  const setCallEmbed = useSetAtom(callEmbedAtom);
  const store = useStore();

  useCallMemberSoundSync(embed);
  useCallThemeSync(embed);
  const clearIfCurrent = useCallback(() => {
    if (store.get(callEmbedAtom) !== embed) return;
    setCallEmbed(undefined);
  }, [store, embed, setCallEmbed]);
  useCallHangupEvent(embed, clearIfCurrent);
  // EC emits Close (not Hangup) when LiveKit gives up without explicit user
  // action — e.g. reconnect fail after a network blip. Without this listener
  // the embed lingers as a zombie and the Android FGS stays up.
  useCallCloseEvent(embed, clearIfCurrent);

  // Widget failed to prepare (bad network, iframe load error). Clear the atom
  // so callEmbedAtom's setter can dispose the embed and the Android FGS
  // (keyed on the atom) stops.
  useEffect(() => {
    const unsubscribe = embed.onPreparingError(clearIfCurrent);
    return unsubscribe;
  }, [embed, clearIfCurrent]);

  return null;
}

type CallEmbedProviderProps = {
  children?: ReactNode;
};
export function CallEmbedProvider({ children }: CallEmbedProviderProps) {
  const callEmbed = useAtomValue(callEmbedAtom);
  const callEmbedRef = useRef<HTMLDivElement>(null);
  const joined = useCallJoined(callEmbed);

  useAndroidCallForegroundSync();

  const selectedRoom = useSelectedRoom();
  const chat = useAtomValue(callChatAtom);
  const screenSize = useScreenSizeContext();

  const chatOnlyView = chat && screenSize !== ScreenSize.Desktop;

  const callVisible =
    callEmbed &&
    !callEmbed.voiceOnly &&
    selectedRoom === callEmbed.roomId &&
    joined &&
    !chatOnlyView;

  return (
    <CallEmbedContextProvider value={callEmbed}>
      {callEmbed && <CallUtils embed={callEmbed} />}
      <CallEmbedRefContextProvider value={callEmbedRef}>{children}</CallEmbedRefContextProvider>
      <div
        data-call-embed-container
        style={{
          visibility: callVisible ? undefined : 'hidden',
          pointerEvents: callVisible ? undefined : 'none',
          position: 'fixed',
          top: 0,
          left: 0,
          width: '100%',
          height: '50%',
        }}
        ref={callEmbedRef}
      />
    </CallEmbedContextProvider>
  );
}
