// src/lib/integrations/youtube/YouTubeClient.ts

import { google, youtube_v3 } from 'googleapis'
import type { Payload } from 'payload'

interface YouTubeCredentials {
  clientId: string
  clientSecret: string
  accessToken: string
  refreshToken: string
}

interface CommentThread {
  id: string
  snippet: {
    videoId: string
    topLevelComment: {
      id: string
      snippet: {
        textDisplay: string
        textOriginal: string
        authorDisplayName: string
        authorProfileImageUrl: string
        authorChannelUrl: string
        authorChannelId: { value: string }
        likeCount: number
        publishedAt: string
        updatedAt: string
      }
    }
    totalReplyCount: number
  }
}

export class YouTubeClient {
  private youtube: youtube_v3.Youtube
  private oauth2Client: InstanceType<typeof google.auth.OAuth2>
  private payload: Payload

  constructor(credentials: YouTubeCredentials, payload: Payload) {
    this.payload = payload

    this.oauth2Client = new google.auth.OAuth2(
      credentials.clientId,
      credentials.clientSecret,
      process.env.YOUTUBE_REDIRECT_URI
    )

    this.oauth2Client.setCredentials({
      access_token: credentials.accessToken,
      refresh_token: credentials.refreshToken,
    })

    this.youtube = google.youtube({
      version: 'v3',
      auth: this.oauth2Client,
    })
  }

  /**
   * Alle Kommentar-Threads eines Videos abrufen
   */
  async getVideoComments(
    videoId: string,
    pageToken?: string,
    maxResults: number = 100
  ): Promise<{
    comments: CommentThread[]
    nextPageToken?: string
  }> {
    try {
      const response = await this.youtube.commentThreads.list({
        part: ['snippet', 'replies'],
        videoId: videoId,
        maxResults: maxResults,
        pageToken: pageToken,
        order: 'time',
        textFormat: 'plainText',
      })

      return {
        comments: response.data.items as CommentThread[],
        nextPageToken: response.data.nextPageToken || undefined,
      }
    } catch (error) {
      console.error('Error fetching comments:', error)
      throw error
    }
  }

  /**
   * Alle Kommentare eines Kanals abrufen (alle Videos)
   */
  async getChannelComments(
    channelId: string,
    publishedAfter?: Date,
    maxResults: number = 100
  ): Promise<CommentThread[]> {
    try {
      const params: youtube_v3.Params$Resource$Commentthreads$List = {
        part: ['snippet', 'replies'],
        allThreadsRelatedToChannelId: channelId,
        maxResults: maxResults,
        order: 'time',
        textFormat: 'plainText',
      }

      const response = await this.youtube.commentThreads.list(params)
      return response.data.items as CommentThread[]
    } catch (error) {
      console.error('Error fetching channel comments:', error)
      throw error
    }
  }

  /**
   * Auf einen Kommentar antworten
   */
  async replyToComment(parentCommentId: string, text: string): Promise<string> {
    try {
      const response = await this.youtube.comments.insert({
        part: ['snippet'],
        requestBody: {
          snippet: {
            parentId: parentCommentId,
            textOriginal: text,
          },
        },
      })

      return response.data.id!
    } catch (error) {
      console.error('Error replying to comment:', error)
      throw error
    }
  }

  /**
   * Kommentar als Spam markieren
   */
  async markAsSpam(commentId: string): Promise<void> {
    try {
      await this.youtube.comments.setModerationStatus({
        id: [commentId],
        moderationStatus: 'rejected',
      })
    } catch (error) {
      console.error('Error marking as spam:', error)
      throw error
    }
  }

  /**
   * Kommentar löschen
   */
  async deleteComment(commentId: string): Promise<void> {
    try {
      await this.youtube.comments.delete({
        id: commentId,
      })
    } catch (error) {
      console.error('Error deleting comment:', error)
      throw error
    }
  }

  /**
   * Heart/Like auf einen Kommentar setzen
   */
  async heartComment(commentId: string): Promise<void> {
    try {
      await this.youtube.comments.setModerationStatus({
        id: [commentId],
        moderationStatus: 'published',
      })
      // Note: YouTube API doesn't directly support "hearting" via API
      // This would require additional implementation
    } catch (error) {
      console.error('Error hearting comment:', error)
      throw error
    }
  }

  /**
   * Access Token erneuern
   */
  async refreshAccessToken(): Promise<{
    accessToken: string
    expiresAt: Date
  }> {
    try {
      const { credentials } = await this.oauth2Client.refreshAccessToken()

      return {
        accessToken: credentials.access_token!,
        expiresAt: new Date(credentials.expiry_date!),
      }
    } catch (error) {
      console.error('Error refreshing token:', error)
      throw error
    }
  }

  /**
   * Video-Statistiken für mehrere Videos abrufen (Batch)
   * YouTube API erlaubt max. 50 IDs pro Request
   */
  async getVideoStatistics(videoIds: string[]): Promise<Array<{
    id: string
    views: number
    likes: number
    comments: number
  }>> {
    if (videoIds.length === 0) return []

    try {
      const response = await this.youtube.videos.list({
        part: ['statistics'],
        id: videoIds,
        maxResults: 50,
      })

      return (response.data.items || []).map((item) => ({
        id: item.id!,
        views: parseInt(item.statistics?.viewCount || '0', 10),
        likes: parseInt(item.statistics?.likeCount || '0', 10),
        comments: parseInt(item.statistics?.commentCount || '0', 10),
      }))
    } catch (error) {
      console.error('Error fetching video statistics:', error)
      throw error
    }
  }

  /**
   * Antworten auf einen Kommentar-Thread abrufen
   */
  async getCommentReplies(
    parentCommentId: string,
    maxResults: number = 100
  ): Promise<{
    replies: Array<{
      id: string
      snippet: {
        parentId: string
        textOriginal: string
        textDisplay: string
        authorDisplayName: string
        authorProfileImageUrl: string
        authorChannelUrl: string
        authorChannelId: { value: string }
        likeCount: number
        publishedAt: string
        updatedAt: string
      }
    }>
    nextPageToken?: string
  }> {
    try {
      const response = await this.youtube.comments.list({
        part: ['snippet'],
        parentId: parentCommentId,
        maxResults,
        textFormat: 'plainText',
      })

      return {
        replies: (response.data.items || []) as any[],
        nextPageToken: response.data.nextPageToken || undefined,
      }
    } catch (error) {
      console.error('Error fetching comment replies:', error)
      throw error
    }
  }

  /**
   * Kanal-Statistiken abrufen
   */
  async getChannelStats(channelId: string): Promise<{
    subscriberCount: number
    videoCount: number
    viewCount: number
  }> {
    try {
      const response = await this.youtube.channels.list({
        part: ['statistics'],
        id: [channelId],
      })

      const stats = response.data.items?.[0]?.statistics
      return {
        subscriberCount: parseInt(stats?.subscriberCount || '0', 10),
        videoCount: parseInt(stats?.videoCount || '0', 10),
        viewCount: parseInt(stats?.viewCount || '0', 10),
      }
    } catch (error) {
      console.error('Error fetching channel stats:', error)
      throw error
    }
  }
}

export type { YouTubeCredentials, CommentThread }
