/**
 * YouTubeClient.getCommentReplies Unit Tests
 *
 * Tests the comment reply retrieval method that fetches replies
 * for a given parent comment thread from the YouTube Data API.
 */

import { describe, it, expect, vi, beforeEach } from 'vitest'

const mockCommentsList = vi.fn()

vi.mock('googleapis', () => {
  class MockOAuth2 {
    setCredentials(): void {
      // no-op
    }
  }

  return {
    google: {
      auth: {
        OAuth2: MockOAuth2,
      },
      youtube: () => ({
        videos: { list: vi.fn() },
        commentThreads: { list: vi.fn() },
        comments: {
          list: mockCommentsList,
          insert: vi.fn(),
          setModerationStatus: vi.fn(),
          delete: vi.fn(),
        },
        channels: { list: vi.fn() },
      }),
    },
  }
})

const mockPayload = {} as import('payload').Payload

describe('YouTubeClient.getCommentReplies', () => {
  beforeEach(() => {
    vi.clearAllMocks()
  })

  it('should return parsed replies for a parent comment', async () => {
    mockCommentsList.mockResolvedValueOnce({
      data: {
        items: [
          {
            id: 'reply-1',
            snippet: {
              parentId: 'comment-abc',
              textOriginal: 'Great point!',
              textDisplay: 'Great point!',
              authorDisplayName: 'User A',
              authorProfileImageUrl: 'https://example.com/a.jpg',
              authorChannelUrl: 'https://youtube.com/channel/UC_a',
              authorChannelId: { value: 'UC_a' },
              likeCount: 5,
              publishedAt: '2026-01-15T10:00:00Z',
              updatedAt: '2026-01-15T10:00:00Z',
            },
          },
          {
            id: 'reply-2',
            snippet: {
              parentId: 'comment-abc',
              textOriginal: 'Thanks for sharing',
              textDisplay: 'Thanks for sharing',
              authorDisplayName: 'User B',
              authorProfileImageUrl: 'https://example.com/b.jpg',
              authorChannelUrl: 'https://youtube.com/channel/UC_b',
              authorChannelId: { value: 'UC_b' },
              likeCount: 2,
              publishedAt: '2026-01-15T11:00:00Z',
              updatedAt: '2026-01-15T11:00:00Z',
            },
          },
        ],
        nextPageToken: undefined,
      },
    })

    const { YouTubeClient } = await import(
      '@/lib/integrations/youtube/YouTubeClient'
    )

    const client = new YouTubeClient(
      {
        clientId: 'test-id',
        clientSecret: 'test-secret',
        accessToken: 'test-token',
        refreshToken: 'test-refresh',
      },
      mockPayload,
    )

    const result = await client.getCommentReplies('comment-abc')

    expect(result.replies).toHaveLength(2)
    expect(result.replies[0].id).toBe('reply-1')
    expect(result.replies[0].snippet.parentId).toBe('comment-abc')
    expect(result.replies[0].snippet.textOriginal).toBe('Great point!')
    expect(result.replies[0].snippet.likeCount).toBe(5)
    expect(result.replies[1].id).toBe('reply-2')
    expect(result.nextPageToken).toBeUndefined()

    expect(mockCommentsList).toHaveBeenCalledWith({
      part: ['snippet'],
      parentId: 'comment-abc',
      maxResults: 100,
      textFormat: 'plainText',
    })
  })

  it('should pass custom maxResults parameter', async () => {
    mockCommentsList.mockResolvedValueOnce({
      data: {
        items: [],
        nextPageToken: undefined,
      },
    })

    const { YouTubeClient } = await import(
      '@/lib/integrations/youtube/YouTubeClient'
    )

    const client = new YouTubeClient(
      {
        clientId: 'test-id',
        clientSecret: 'test-secret',
        accessToken: 'test-token',
        refreshToken: 'test-refresh',
      },
      mockPayload,
    )

    await client.getCommentReplies('comment-xyz', 20)

    expect(mockCommentsList).toHaveBeenCalledWith({
      part: ['snippet'],
      parentId: 'comment-xyz',
      maxResults: 20,
      textFormat: 'plainText',
    })
  })

  it('should return empty replies array when no items exist', async () => {
    mockCommentsList.mockResolvedValueOnce({
      data: {
        items: null,
        nextPageToken: undefined,
      },
    })

    const { YouTubeClient } = await import(
      '@/lib/integrations/youtube/YouTubeClient'
    )

    const client = new YouTubeClient(
      {
        clientId: 'test-id',
        clientSecret: 'test-secret',
        accessToken: 'test-token',
        refreshToken: 'test-refresh',
      },
      mockPayload,
    )

    const result = await client.getCommentReplies('comment-empty')

    expect(result.replies).toEqual([])
    expect(result.nextPageToken).toBeUndefined()
  })

  it('should return nextPageToken when more replies are available', async () => {
    mockCommentsList.mockResolvedValueOnce({
      data: {
        items: [
          {
            id: 'reply-page1',
            snippet: {
              parentId: 'comment-many',
              textOriginal: 'First page reply',
              textDisplay: 'First page reply',
              authorDisplayName: 'User C',
              authorProfileImageUrl: 'https://example.com/c.jpg',
              authorChannelUrl: 'https://youtube.com/channel/UC_c',
              authorChannelId: { value: 'UC_c' },
              likeCount: 0,
              publishedAt: '2026-02-01T12:00:00Z',
              updatedAt: '2026-02-01T12:00:00Z',
            },
          },
        ],
        nextPageToken: 'page2token',
      },
    })

    const { YouTubeClient } = await import(
      '@/lib/integrations/youtube/YouTubeClient'
    )

    const client = new YouTubeClient(
      {
        clientId: 'test-id',
        clientSecret: 'test-secret',
        accessToken: 'test-token',
        refreshToken: 'test-refresh',
      },
      mockPayload,
    )

    const result = await client.getCommentReplies('comment-many')

    expect(result.replies).toHaveLength(1)
    expect(result.nextPageToken).toBe('page2token')
  })

  it('should propagate API errors', async () => {
    mockCommentsList.mockRejectedValueOnce(new Error('commentListForbidden'))

    const { YouTubeClient } = await import(
      '@/lib/integrations/youtube/YouTubeClient'
    )

    const client = new YouTubeClient(
      {
        clientId: 'test-id',
        clientSecret: 'test-secret',
        accessToken: 'test-token',
        refreshToken: 'test-refresh',
      },
      mockPayload,
    )

    await expect(
      client.getCommentReplies('comment-forbidden'),
    ).rejects.toThrow('commentListForbidden')
  })
})
