"use strict";

import React, { useEffect, useMemo, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import ChatRoom from './ChatRoom';
import { setActiveModal, setConfig, setDeleteModal, setStoreClient } from '../../roomStore/chatSettingsSlice';
import { ChatWrapperBox } from '../styled/ChatWrapperBox';
import { Overlay } from '../styled/MediaModal';
import ConnectionBanner from './ConnectionBanner';
import { Message } from '../MessageBubble/Message';
import { useXmppClient } from '../../context/xmppProvider';
import LoginForm from '../AuthForms/Login';
import Loader from '../styled/Loader';
import { setCurrentRoom, setEditAction, setIsLoading } from '../../roomStore/roomsSlice';
import { refresh } from '../../networking/apiClient';
import RoomList from './RoomList';
import { StyledLoaderWrapper } from '../styled/StyledComponents';
import Modal from '../Modals/Modal/Modal';
import { ModalWrapper } from '../Modals/ModalWrapper/ModalWrapper';
import { useChatSettingState } from '../../hooks/useChatSettingState';
import { DeviceEventEmitter, Pressable, Text, View } from 'react-native';
import { pushLog as devPushLog } from '../../utils/devLogger';
import { normalizeRoomJid } from '../../helpers/normalizeRoomJid';
import { InteractionsOverlayProvider } from '../MessageBubble/InteractionsOverlay';
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
const ChatWrapper = ({
  MainComponentStyles,
  CustomMessageComponent,
  room,
  config,
  roomJID
}) => {
  const {
    user,
    activeModal,
    deleteModal,
    client: storedClient
  } = useChatSettingState();
  const [isInited, setInited] = useState(false);
  const [showModal, setShowModal] = useState(false);
  const [errorMsg, setErrorMsg] = useState(null);
  // const [isModalDeleteOpen, setIsModalDeleteOpen] = useState(false);

  const [isChatVisible, setIsChatVisible] = useState(false);
  const [isSmallScreen, setIsSmallScreen] = useState(false);
  const handleItemClick = value => {
    setIsChatVisible(value);
  };
  const dispatch = useDispatch();
  const {
    client,
    initializeClient,
    setClient,
    providerBootstrapStatus,
    initMode
  } = useXmppClient();
  const {
    rooms,
    activeRoomJID
  } = useSelector(state => state.rooms);
  const activeMessage = useMemo(() => {
    if (activeRoomJID) {
      return rooms[activeRoomJID]?.messages?.find(message => message?.activeMessage);
    }
  }, [rooms, activeRoomJID]);
  const handleChangeChat = chat => {
    dispatch(setCurrentRoom({
      roomJID: chat.jid
    }));
    activeRoomJID !== chat.jid && dispatch(setIsLoading({
      chatJID: chat.jid,
      loading: true
    }));
    dispatch(setEditAction({
      isEdit: false
    }));
    handleItemClick(true);
  };
  const handleDeleteClick = () => {
    if (!client || !deleteModal?.roomJid || !deleteModal?.messageId) {
      dispatch(setDeleteModal({
        isDeleteModal: false
      }));
      return;
    }
    client.deleteMessageStanza(deleteModal.roomJid, deleteModal.messageId);
    dispatch(setDeleteModal({
      isDeleteModal: false
    }));
  };
  const handleCloseDeleteModal = () => {
    dispatch(setDeleteModal({
      isDeleteModal: false
    }));
  };
  useEffect(() => {
    return () => {
      if (client && user.xmppPassword === '') {
        console.log('closing client');
        client.close();
        setClient(null);
      }
    };
  }, [user.xmppPassword]);

  // Tell the XMPP client which room is currently active so the QoS
  // scheduler can prioritize its history fetches.
  useEffect(() => {
    if (!client) {
      return;
    }
    client.setActiveRoomJid?.(activeRoomJID || null);
  }, [client, activeRoomJID]);
  useEffect(() => {
    if (roomJID) {
      dispatch(setCurrentRoom({
        roomJID: normalizeRoomJid(roomJID, config?.xmppSettings?.conference)
      }));
    }
    const initXmmpClient = async () => {
      // Only sync config to redux if we have one — passing `undefined`
      // wipes whatever XmppProvider already set up.
      if (config) {
        dispatch(setConfig(config));
      }
      try {
        const hasUser = !!user?.defaultWallet?.walletAddress && user?.defaultWallet.walletAddress !== '' && !!user?.xmppPassword;

        // initBeforeLoad path — provider owns auth + xmpp connect; we just wait.
        if (config?.initBeforeLoad && initMode === 'provider') {
          if (providerBootstrapStatus === 'failed') {
            devPushLog('error', 'ChatWrapper: bootstrap failed');
            setErrorMsg('Could not authenticate against the server.\n' + 'Check baseUrl, XMPP host fields, and the token / credentials you entered.');
            setShowModal(true);
            setInited(false);
            return;
          }
          if (providerBootstrapStatus !== 'ready') {
            // 'idle' or 'running' → just wait; effect will re-run when status flips.
            devPushLog('rn', `ChatWrapper: waiting for provider (${providerBootstrapStatus})`);
            return;
          }
          // ready — fall through to client wiring below
        }
        if (!hasUser) {
          // No user yet. In initBeforeLoad mode this is normal during the
          // bootstrap window; show the loader (no modal). In legacy mode
          // it's an error.
          if (config?.initBeforeLoad) {
            devPushLog('rn', 'ChatWrapper: no user yet, awaiting provider');
            setShowModal(false);
            return;
          }
          devPushLog('error', 'ChatWrapper: no user (legacy login path)');
          setErrorMsg('No authenticated user available.\n' + 'For JWT login pass `jwtLogin.token`; for email login pass the `user={{email,password}}` prop and `customAppToken`.');
          setShowModal(true);
          return;
        }

        // We have a user. Modal should be down.
        setShowModal(false);
        setErrorMsg(null);
        if (!client && !storedClient) {
          devPushLog('rn', 'ChatWrapper: initing xmpp client (legacy path)');
          // The outer `.then(c => {...})` used to lack a `.catch()` —
          // if initializeClient rejected (network / SASL), the outer
          // try/catch couldn't see it because the rejection happens in
          // the .then handler, not in the awaited promise itself.
          // Convert to await + try/catch.
          try {
            const c = await initializeClient(user.xmppUsername || user.defaultWallet?.walletAddress, user.xmppPassword, config?.xmppSettings);
            try {
              await c.getRoomsStanza();
              c.getChatsPrivateStoreRequestStanza().catch(err => console.warn('getChatsPrivateStoreRequestStanza failed', err));
              dispatch(setStoreClient(c));
              setClient(c);
            } catch (err) {
              console.warn('getRoomsStanza failed', err);
            }
          } catch (err) {
            devPushLog('warn', 'initializeClient failed (legacy path)', err);
          }
          setInited(true);
          if (config?.refreshTokens?.enabled) {
            // refresh() is fire-and-forget but rejects on bad
            // refreshToken / network — surface via .catch instead of
            // leaving the rejection unhandled (was bug #4, id:2).
            refresh().catch(err => console.warn('refresh failed', err));
          }
        } else if (storedClient) {
          devPushLog('rn', 'ChatWrapper: reusing storedClient');
          setClient(storedClient);
          if (!activeRoomJID) {
            storedClient.getRoomsStanza().then(() => {
              storedClient.getChatsPrivateStoreRequestStanza().catch(err => console.warn('getChatsPrivateStoreRequestStanza failed', err));
            }).catch(err => console.warn('getRoomsStanza failed', err));
          }
          setInited(true);
          if (config?.refreshTokens?.enabled) {
            refresh().catch(err => console.warn('refresh failed', err));
          }
        } else if (client) {
          devPushLog('rn', 'ChatWrapper: reusing provider client');
          if (!activeRoomJID) {
            client.getRoomsStanza().then(() => {
              client.getChatsPrivateStoreRequestStanza().catch(err => console.warn('getChatsPrivateStoreRequestStanza failed', err));
            }).catch(err => console.warn('getRoomsStanza failed', err));
          }
          client.getChatsPrivateStoreRequestStanza().catch(err => console.warn('getChatsPrivateStoreRequestStanza failed', err));
          setInited(true);
          if (config?.refreshTokens?.enabled) {
            refresh().catch(err => console.warn('refresh failed', err));
          }
        }
        dispatch(setIsLoading({
          loading: false
        }));
      } catch (error) {
        devPushLog('error', 'ChatWrapper: init failed', error);
        const msg = error?.response?.data?.message || error?.message || String(error);
        setErrorMsg(`Init failed: ${msg}`);
        setShowModal(true);
        setInited(false);
        dispatch(setIsLoading({
          loading: false
        }));
      }
    };
    initXmmpClient();
  }, [user.xmppPassword, user.defaultWallet, providerBootstrapStatus, initMode, config?.initBeforeLoad]);

  // Cache-first display (initBeforeLoad). The main effect above only marks
  // the chat `inited` once the provider bootstrap reaches 'ready' — which
  // waits on the cold XMPP connect. On re-entry that left the user staring
  // at a loader while fully-cached rooms/messages sat in redux-persist
  // ("pulls a new connection for 100 years"). Here we render the cached
  // content the instant rehydration lands; the live client gets wired by
  // the main effect when the connect completes (send/loadMore activate
  // then). Mirrors web showing cached rooms immediately + refreshing in
  // the background.
  useEffect(() => {
    if (!config?.initBeforeLoad || initMode !== 'provider') {
      return;
    }
    if (isInited || showModal) {
      return;
    }
    if (providerBootstrapStatus === 'failed') {
      return;
    }
    const haveCachedRooms = !!rooms && Object.keys(rooms).length > 0;
    const haveUser = !!user?.xmppUsername || !!user?.defaultWallet?.walletAddress;
    if (haveCachedRooms && haveUser) {
      devPushLog('rn', 'ChatWrapper: cache-first — showing persisted rooms while provider connects');
      setShowModal(false);
      setInited(true);
    }
  }, [config?.initBeforeLoad, initMode, isInited, showModal, providerBootstrapStatus, rooms, user?.xmppUsername, user?.defaultWallet?.walletAddress]);

  // Skip the legacy email/password LoginForm entirely when XmppProvider
  // is driving auth via initBeforeLoad — the bootstrap effect will
  // populate the user shortly. Showing LoginForm here causes a flicker
  // and (worse) a stale form that races against the in-flight bootstrap.
  if (user.xmppPassword === '' && user.xmppUsername === '' && !config?.initBeforeLoad) {
    return /*#__PURE__*/_jsx(LoginForm, {
      config: config
    });
  }

  // Mirror the web layout: when `disableRooms` is false and the
  // consumer didn't preselect a `roomJID`, show the RoomList until the
  // user picks one; then show the chat with a back button to return to
  // the list. With `roomJID` or `disableRooms`, skip the list entirely.
  const showRoomList = !config?.disableRooms && !roomJID && !activeRoomJID;
  return /*#__PURE__*/_jsxs(_Fragment, {
    children: [showModal && config?.disableConnectionErrorOverlay && /*#__PURE__*/_jsx(ConnectionBanner, {}), showModal && !config?.disableConnectionErrorOverlay && /*#__PURE__*/_jsx(Overlay, {
      children: /*#__PURE__*/_jsxs(View, {
        style: {
          padding: 20,
          backgroundColor: '#fff',
          borderRadius: 12,
          maxWidth: 320,
          alignItems: 'stretch'
        },
        children: [/*#__PURE__*/_jsx(Text, {
          style: {
            fontSize: 16,
            fontWeight: '600',
            marginBottom: 8,
            color: '#222'
          },
          children: "Connection error"
        }), /*#__PURE__*/_jsx(Text, {
          style: {
            fontSize: 13,
            color: '#444',
            marginBottom: 16
          },
          children: errorMsg ?? 'Something went wrong while connecting to chat.'
        }), /*#__PURE__*/_jsx(Pressable, {
          onPress: () => {
            setShowModal(false);
            setErrorMsg(null);
            setInited(false);
            // Signal a clean re-bootstrap. XmppProvider listens and
            // resets its state machine so the next effect run resolves
            // the user from scratch.
            DeviceEventEmitter.emit('ethora:retryBootstrap');
          },
          style: ({
            pressed
          }) => ({
            paddingVertical: 10,
            paddingHorizontal: 16,
            borderRadius: 6,
            backgroundColor: pressed ? '#0040A0' : '#0052CD',
            alignItems: 'center'
          }),
          children: /*#__PURE__*/_jsx(Text, {
            style: {
              color: '#fff',
              fontWeight: '600'
            },
            children: "Retry"
          })
        })]
      })
    }), /*#__PURE__*/_jsx(_Fragment, {
      children: isInited ? /*#__PURE__*/_jsxs(ChatWrapperBox, {
        style: {
          ...MainComponentStyles
        },
        children: [/*#__PURE__*/_jsx(InteractionsOverlayProvider, {
          children: showRoomList ? /*#__PURE__*/_jsx(RoomList, {
            chats: Object.values(rooms),
            onRoomClick: handleChangeChat
          }) : /*#__PURE__*/_jsx(ChatWrapperBox, {
            style: {
              ...MainComponentStyles
            },
            children: /*#__PURE__*/_jsx(ChatRoom, {
              CustomMessageComponent: CustomMessageComponent || Message,
              handleBackClick: roomJID || config?.disableRooms ? undefined : () => {
                dispatch(setCurrentRoom({
                  roomJID: ''
                }));
              }
            })
          })
        }), /*#__PURE__*/_jsx(Modal, {
          modal: activeModal,
          setOpenModal: value => dispatch(setActiveModal(value))
        }), deleteModal?.isDeleteModal && /*#__PURE__*/_jsx(ModalWrapper, {
          title: "Delete Message",
          description: "Are you sure you want to delete this message?",
          buttonText: "Delete",
          backgroundColorButton: "#E53935",
          handleClick: handleDeleteClick,
          handleCloseModal: handleCloseDeleteModal,
          compact: true
        })]
      }) : /*#__PURE__*/_jsx(StyledLoaderWrapper, {
        children: /*#__PURE__*/_jsx(Loader, {
          color: config?.colors?.primary
        })
      })
    })]
  });
};
export { ChatWrapper };
//# sourceMappingURL=ChatWrapper.js.map