import React from 'react'
import type { Attachment, LocalMessage } from 'stream-chat'
import { describe, expect, it } from 'vitest'

import { fireEvent, renderWithProviders, screen } from '../../test/utils'

import StreamAttachmentMessage, {
  linkCaptionDuplicatesAttachmentUrl,
  linkCardPropsFromStreamAttachment,
} from './StreamAttachmentMessage'

const message = (attachments: Attachment[], text?: string): LocalMessage =>
  ({ attachments, text }) as LocalMessage

describe('linkCardPropsFromStreamAttachment', () => {
  it('uses the featured layout when a thumbnail is present', () => {
    expect(
      linkCardPropsFromStreamAttachment({
        type: 'link',
        og_scrape_url: 'https://linktr.ee/someone',
        image_url: 'https://cdn.example.com/thumb.jpg',
      }).layout
    ).toBe('featured')
  })

  it('optimizes Linktree-hosted thumbnails for messaging attachment renders', () => {
    expect(
      linkCardPropsFromStreamAttachment({
        type: 'link',
        og_scrape_url: 'https://linktr.ee/someone',
        image_url: 'https://assets.linktr.ee/thumb.jpg',
      }).thumbnailUrl
    ).toBe(
      'https://assets.linktr.ee/thumb.jpg?io=true&size=messaging-attachment-v1_0'
    )
  })

  it('uses the classic layout for a plain link with no thumbnail', () => {
    expect(
      linkCardPropsFromStreamAttachment({
        type: 'link',
        og_scrape_url: 'https://linktr.ee/someone',
      }).layout
    ).toBe('classic')
  })

  it('keeps the featured layout for a playable clip with no thumbnail so the player renders', () => {
    expect(
      linkCardPropsFromStreamAttachment({
        type: 'link',
        og_scrape_url: 'https://linktr.ee/someone',
        asset_url: 'https://cdn.example.com/clip.mp3',
        mime_type: 'audio/mpeg',
      }).layout
    ).toBe('featured')
  })
})

describe('linkCaptionDuplicatesAttachmentUrl', () => {
  it('suppresses captions that are just the link plus punctuation', () => {
    expect(
      linkCaptionDuplicatesAttachmentUrl(
        'https://tr.ee/abc !',
        'https://tr.ee/abc'
      )
    ).toBe(true)
  })

  it('keeps captions that add emoji after the link', () => {
    expect(
      linkCaptionDuplicatesAttachmentUrl(
        'https://tr.ee/abc 😎',
        'https://tr.ee/abc'
      )
    ).toBe(false)
  })
})

describe('StreamAttachmentMessage', () => {
  it('renders a sent link card and suppresses a URL-only caption', () => {
    renderWithProviders(
      <StreamAttachmentMessage
        groupPosition="single"
        isMyMessage={true}
        message={message(
          [
            {
              type: 'link',
              og_scrape_url: 'https://linktr.ee/someone',
              title: 'My Linktree',
              text: 'Check out my links',
              image_url: 'https://cdn.example.com/thumb.jpg',
            },
          ],
          'https://linktr.ee/someone !'
        )}
      />
    )

    expect(screen.getByRole('link', { name: /my linktree/i })).toHaveAttribute(
      'href',
      'https://linktr.ee/someone'
    )
    expect(screen.queryByText('https://linktr.ee/someone !')).toBeNull()
  })

  it('keeps an emoji-only caption instead of dropping it', () => {
    const { container } = renderWithProviders(
      <StreamAttachmentMessage
        groupPosition="single"
        isMyMessage={false}
        message={message(
          [
            {
              type: 'link',
              og_scrape_url: 'https://linktr.ee/someone',
              title: 'My Linktree',
            },
          ],
          'https://linktr.ee/someone 😎'
        )}
      />
    )

    // MessageText linkifies the URL (display text drops the scheme), so the
    // caption is split across a link node and trailing emoji text.
    const captionBubble = container.querySelector(
      '.str-chat__message-bubble:not([data-attachment-bubble])'
    )
    expect(captionBubble).toHaveTextContent('linktr.ee/someone')
    expect(captionBubble).toHaveTextContent('😎')
  })

  it('renders mixed link and media attachments in order', () => {
    const { container } = renderWithProviders(
      <StreamAttachmentMessage
        groupPosition="single"
        isMyMessage={true}
        message={message(
          [
            {
              type: 'link',
              og_scrape_url: 'https://linktr.ee/someone',
              title: 'My Linktree',
            },
            {
              type: 'image',
              image_url: 'https://cdn.example.com/photo.jpg',
              title: 'Vacation',
            },
          ],
          'caption'
        )}
      />
    )

    const link = screen.getByRole('link', { name: /my linktree/i })
    const imageBubble = screen.getByTestId('image-attachment')

    expect(link.compareDocumentPosition(imageBubble)).toBe(
      Node.DOCUMENT_POSITION_FOLLOWING
    )
    expect(container).toHaveTextContent('caption')
  })

  it('optimizes Linktree-hosted image attachments for the channel bubble', () => {
    renderWithProviders(
      <StreamAttachmentMessage
        groupPosition="single"
        isMyMessage={false}
        message={message([
          {
            type: 'image',
            image_url: 'https://ugc.production.linktr.ee/photo.jpg',
            title: 'Vacation',
          },
        ])}
      />
    )

    expect(screen.getByRole('img', { name: 'Vacation' })).toHaveAttribute(
      'src',
      'https://ugc.production.linktr.ee/photo.jpg?io=true&size=messaging-attachment-v1_0'
    )
  })

  it('optimizes Linktree-hosted video posters for the channel bubble', () => {
    renderWithProviders(
      <StreamAttachmentMessage
        groupPosition="single"
        isMyMessage
        message={message([
          {
            type: 'video',
            asset_url: 'https://ugc.production.linktr.ee/clip.mp4',
            thumb_url: 'https://ugc.production.linktr.ee/poster.jpg',
            mime_type: 'video/mp4',
          },
        ])}
      />
    )

    // Video posters were the last media URL leaving here at full size —
    // four of them per 2×2 grid.
    expect(
      screen.getByTestId('video-attachment').querySelector('img')
    ).toHaveAttribute(
      'src',
      'https://ugc.production.linktr.ee/poster.jpg?io=true&size=messaging-attachment-v1_0'
    )
  })

  it('keeps the original image source in the viewer for channel image attachments', () => {
    renderWithProviders(
      <StreamAttachmentMessage
        groupPosition="single"
        isMyMessage={false}
        message={message([
          {
            type: 'image',
            image_url: 'https://ugc.production.linktr.ee/photo.jpg',
            title: 'Vacation',
          },
        ])}
      />
    )

    fireEvent.click(screen.getByLabelText('Open image 1 of 1'))
    const viewer = screen.getByTestId('image-viewer')

    expect(viewer).toHaveAttribute('open')
    expect(viewer.querySelector('img')?.getAttribute('src')).toBe(
      'https://ugc.production.linktr.ee/photo.jpg'
    )
  })

  it('renders the accompanying message text next to a link attachment', () => {
    const { container } = renderWithProviders(
      <StreamAttachmentMessage
        groupPosition="single"
        isMyMessage={true}
        message={message(
          [
            {
              type: 'link',
              og_scrape_url: 'https://linktr.ee/someone',
              title: 'My Linktree',
            },
          ],
          'you have to see this'
        )}
      />
    )

    const bubbles = container.querySelectorAll('.str-chat__message-bubble')
    expect(bubbles).toHaveLength(2)
    expect(bubbles[0]).toHaveAttribute('data-attachment-bubble', 'true')
    expect(bubbles[1]).toHaveTextContent('you have to see this')
  })

  it('renders the accompanying message text next to a media attachment', () => {
    const { container } = renderWithProviders(
      <StreamAttachmentMessage
        groupPosition="single"
        isMyMessage={false}
        message={message(
          [
            {
              type: 'image',
              image_url: 'https://cdn.example.com/photo.jpg',
              title: 'Vacation',
            },
          ],
          'from the trip'
        )}
      />
    )

    expect(container).toHaveTextContent('from the trip')
    expect(
      container.querySelector(
        '.str-chat__message-bubble:not([data-attachment-bubble])'
      )
    ).toHaveTextContent('from the trip')
  })
})
