import { describe, it, expect } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { MessagingProvider } from '../provider';
import { Messenger } from './messenger';
import { MockAdapter } from '../adapters/mock';

function mount() {
  return render(
    <MessagingProvider adapter={new MockAdapter()}>
      <Messenger />
    </MessagingProvider>,
  );
}

describe('channels (mock adapter)', () => {
  it('browse returns public channels + private ones I am in, with a joined flag', async () => {
    const a = new MockAdapter();
    const list = await a.browseChannels();
    const byId = new Map(list.map((c) => [c.threadId, c]));
    expect(byId.get('th_ch_general')?.joined).toBe(true); // public, I'm in
    expect(byId.get('th_ch_random')?.joined).toBe(false); // public, I'm NOT in
    expect(byId.get('th_ch_deals')?.joined).toBe(true); // private, I'm in
    // A private channel I'm not in must never surface in browse — none seeded, so all private here are mine.
    expect(list.every((c) => c.visibility === 'public' || c.joined)).toBe(true);
  });

  it('join adds me and the channel then appears in my conversation list', async () => {
    const a = new MockAdapter();
    expect((await a.listConversations()).some((c) => c.threadId === 'th_ch_random')).toBe(false);
    await a.joinChannel('th_ch_random');
    expect((await a.listConversations()).some((c) => c.threadId === 'th_ch_random')).toBe(true);
    expect((await a.browseChannels()).find((c) => c.threadId === 'th_ch_random')?.joined).toBe(true);
  });

  it('create makes a channel I am a member of', async () => {
    const a = new MockAdapter();
    const { threadId } = await a.createChannel({ name: 'design', topic: 'UI stuff', visibility: 'public' });
    const conv = (await a.listConversations()).find((c) => c.threadId === threadId);
    expect(conv?.membership).toBe('channel');
    expect(conv?.topic).toBe('UI stuff');
  });

  it('UI: browse, then join a channel — it moves into the Channels section', async () => {
    mount();
    // Open the browser via the Channels section "+".
    fireEvent.click(await screen.findByTitle('Browse channels'));
    // #random is browse-only (not joined) → has a Join button.
    expect(await screen.findByText('random')).toBeTruthy();
    const joinButtons = screen.getAllByText('Join');
    fireEvent.click(joinButtons[0]!);
    // After joining, we jump to the thread and the browser closes → composer is shown.
    await waitFor(() => expect(screen.getByLabelText('Message')).toBeTruthy());
  });
});
