import { act, render, screen } from '@testing-library/react'
import React, { useEffect } from 'react'
import { Channel as StreamChannel, StreamChat } from 'stream-chat'
import { Channel, Chat } from 'stream-chat-react'
import { describe, expect, it, vi } from 'vitest'

import { ChannelView } from './ChannelView'

const message = {
  id: 'message-1',
  cid: 'messaging:channel-1',
  type: 'regular',
  text: 'July class details',
  status: 'received',
  user: { id: 'linker-1', name: 'Linker' },
  metadata: {
    outbound_id: 'outbound-1',
  },
  attachments: [],
  latest_reactions: [],
  own_reactions: [],
  reaction_counts: {},
  reaction_scores: {},
  reply_count: 0,
  mentioned_users: [],
  created_at: new Date(),
  updated_at: new Date(),
}

const createChannel = () => {
  const client = new StreamChat('mock-api-key', {
    allowServerSideConnect: true,
  })
  client.userID = 'linker-1'
  client.user = { id: 'linker-1', name: 'Linker' }

  const channel = client.channel('messaging', 'channel-1')
  channel.initialized = true
  channel.state.messages = [message] as never
  channel.state.members = {
    'linker-1': {
      user: { id: 'linker-1', name: 'Linker' },
      user_id: 'linker-1',
      role: 'owner',
    },
    'visitor-1': {
      user: { id: 'visitor-1', name: 'Visitor' },
      user_id: 'visitor-1',
      role: 'member',
    },
  } as never

  return { channel, client }
}

describe('ChannelView outbound resolution', () => {
  it('updates an existing Stream message row when its outbound record lookup resolves', async () => {
    const { channel, client } = createChannel()
    const firstResolver = () => undefined
    const secondResolver = () => ({
      id: 'automation-1',
      name: 'July 9th Class absentee',
    })
    const mounts = vi.fn()
    const unmounts = vi.fn()

    const RowProbe = ({ children }: { children: React.ReactNode }) => {
      useEffect(() => {
        mounts()
        return unmounts
      }, [])
      return <>{children}</>
    }
    const renderMessage = (messageNode: React.ReactElement) => (
      <RowProbe>{messageNode}</RowProbe>
    )

    let rerender!: ReturnType<typeof render>['rerender']
    await act(async () => {
      rerender = render(
        <Chat client={client}>
          <Channel channel={channel as StreamChannel}>
            <ChannelView
              channel={channel as StreamChannel}
              resolveOutbound={firstResolver}
              renderMessage={renderMessage}
            />
          </Channel>
        </Chat>
      ).rerender
    })

    expect(
      screen.queryByTestId('sent-message-outbound-status')
    ).not.toBeInTheDocument()
    expect(mounts).toHaveBeenCalledOnce()

    act(() => {
      rerender(
        <Chat client={client}>
          <Channel channel={channel as StreamChannel}>
            <ChannelView
              channel={channel as StreamChannel}
              resolveOutbound={secondResolver}
              renderMessage={renderMessage}
            />
          </Channel>
        </Chat>
      )
    })

    expect(
      screen.getByTestId('sent-message-outbound-status')
    ).toHaveTextContent('July 9th Class absentee')
    expect(mounts).toHaveBeenCalledOnce()
    expect(unmounts).not.toHaveBeenCalled()
  })
})
