import { useEffect, useMemo, useState } from 'react';
import { useConversations } from '../hooks/use-conversations';
import { useAdapter } from '../provider';
import { ConversationList } from './conversation-list';
import { ChannelBrowser } from './channel-browser';
import { NewConversation } from './new-conversation';
import { Thread } from './thread';
import { ThreadPane } from './thread-pane';

/**
 * The drop-in messenger: sectioned conversation list (Channels / Direct messages) + open thread,
 * with a channel browser when the adapter supports channels. Owns only selection + browse state;
 * all data flows through the injected adapter via the hooks.
 */
export function Messenger({ focusThreadId }: { focusThreadId?: string | null } = {}) {
  const { conversations, loading, error, refetch } = useConversations();
  const adapter = useAdapter();
  const channelsSupported = typeof adapter.browseChannels === 'function';
  const directorySupported = typeof adapter.directory === 'function';

  const [selected, setSelected] = useState<string | null>(null);
  const [browsing, setBrowsing] = useState(false);
  const [composing, setComposing] = useState(false); // "New message" people picker open
  const [activeRoot, setActiveRoot] = useState<string | null>(null); // open thread pane's root message

  useEffect(() => {
    if (browsing || composing) return;
    if (selected && conversations.some((c) => c.threadId === selected)) return;
    setSelected(conversations[0]?.threadId ?? null);
  }, [conversations, selected, browsing, composing]);

  // Switching conversations (or into browse/compose) closes any open thread pane.
  useEffect(() => setActiveRoot(null), [selected, browsing, composing]);

  // Deep link (e.g. from global search): focus the requested conversation.
  useEffect(() => {
    if (!focusThreadId) return;
    setBrowsing(false);
    setComposing(false);
    setSelected(focusThreadId);
  }, [focusThreadId]);

  // Presence: tell the backend which thread is foregrounded so it suppresses push for it. Null while
  // browsing/composing, when the window is blurred, and on unmount (leaving the messenger).
  useEffect(() => {
    const active = browsing || composing ? null : selected;
    adapter.setFocus?.(active);
    const onBlur = (): void => adapter.setFocus?.(null);
    const onFocus = (): void => adapter.setFocus?.(active);
    window.addEventListener('blur', onBlur);
    window.addEventListener('focus', onFocus);
    return () => {
      adapter.setFocus?.(null);
      window.removeEventListener('blur', onBlur);
      window.removeEventListener('focus', onFocus);
    };
  }, [adapter, selected, browsing, composing]);

  // Live unread + ordering: refresh the conversation list when any of the caller's threads gets a
  // message (not just the open one).
  useEffect(() => {
    if (!adapter.subscribeActivity) return;
    return adapter.subscribeActivity(() => refetch());
  }, [adapter, refetch]);

  const channels = useMemo(() => conversations.filter((c) => c.membership === 'channel'), [conversations]);
  const dms = useMemo(() => conversations.filter((c) => c.membership !== 'channel'), [conversations]);
  const selectedConversation = useMemo(() => conversations.find((c) => c.threadId === selected) ?? null, [conversations, selected]);

  function pick(threadId: string): void {
    setBrowsing(false);
    setComposing(false);
    setSelected(threadId);
  }

  function openBrowse(): void {
    setComposing(false);
    setBrowsing(true);
  }

  function openCompose(): void {
    setBrowsing(false);
    setComposing(true);
  }

  return (
    <div className="miu-messenger">
      <aside className="miu-sidebar">
        {loading && conversations.length === 0 ? <div className="miu-empty">Loading…</div> : null}
        {error ? <div className="miu-empty miu-error">{error}</div> : null}

        {channelsSupported ? (
          <div className="miu-section">
            <div className="miu-section-head">
              <span>Channels</span>
              <button type="button" className="miu-section-add" title="Browse channels" onClick={openBrowse}>
                ＋
              </button>
            </div>
            {channels.length > 0 ? (
              <ConversationList conversations={channels} selectedId={browsing || composing ? null : selected} onSelect={pick} />
            ) : (
              <div className="miu-empty miu-empty-sm">Browse to join a channel.</div>
            )}
          </div>
        ) : null}

        <div className="miu-section">
          {channelsSupported || directorySupported ? (
            <div className="miu-section-head">
              <span>Direct messages</span>
              {directorySupported ? (
                <button type="button" className="miu-section-add" title="New message" onClick={openCompose}>
                  ＋
                </button>
              ) : null}
            </div>
          ) : null}
          <ConversationList conversations={dms} selectedId={browsing || composing ? null : selected} onSelect={pick} />
        </div>
      </aside>

      <section className="miu-main">
        {browsing ? (
          <ChannelBrowser
            onJoined={(threadId) => {
              refetch();
              pick(threadId);
            }}
          />
        ) : composing ? (
          <NewConversation
            onCreated={(threadId) => {
              refetch();
              pick(threadId);
            }}
          />
        ) : (
          <Thread
            threadId={selected}
            conversation={selectedConversation}
            activeRootId={activeRoot}
            onOpenThread={setActiveRoot}
            onLeft={() => {
              refetch();
              setSelected(null);
            }}
          />
        )}
      </section>

      {!browsing && !composing && selected && activeRoot ? (
        <ThreadPane threadId={selected} rootId={activeRoot} onClose={() => setActiveRoot(null)} />
      ) : null}
    </div>
  );
}
