// src/lib/integrations/youtube/VideoMetricsSyncService.ts

import type { Payload } from 'payload'

import { YouTubeClient } from './YouTubeClient'

const YOUTUBE_API_BATCH_LIMIT = 50

interface MetricsSyncResult {
  success: boolean
  syncedCount: number
  skippedCount: number
  errors: string[]
  syncedAt: Date
}

/**
 * Syncs video performance metrics from YouTube API to YouTubeContent.performance fields.
 *
 * Fetches view counts, like counts, and comment counts for all published/tracked
 * videos of a given channel and updates their performance fields in the database.
 */
export class VideoMetricsSyncService {
  private payload: Payload

  constructor(payload: Payload) {
    this.payload = payload
  }

  /**
   * Sync metrics for all published/tracked videos of a YouTube channel.
   */
  async syncMetrics(channelId: number): Promise<MetricsSyncResult> {
    const result: MetricsSyncResult = {
      success: false,
      syncedCount: 0,
      skippedCount: 0,
      errors: [],
      syncedAt: new Date(),
    }

    try {
      // 1. Load the YouTube channel
      const channel = await this.payload.findByID({
        collection: 'youtube-channels',
        id: channelId,
      })

      if (!channel) {
        result.errors.push(`YouTube channel with ID ${channelId} not found`)
        return result
      }

      // 2. Find the social account linked to this channel
      const socialAccounts = await this.payload.find({
        collection: 'social-accounts',
        where: {
          linkedChannel: { equals: channelId },
          isActive: { equals: true },
        },
        limit: 1,
      })

      const account = socialAccounts.docs[0]
      if (!account) {
        result.errors.push(`No active social account found for channel ${channelId}`)
        return result
      }

      // 3. Validate credentials
      const credentials = account.credentials as {
        accessToken?: string
        refreshToken?: string
      } | undefined

      if (!credentials?.accessToken || !credentials?.refreshToken) {
        result.errors.push('No valid API credentials on social account')
        return result
      }

      // 4. Initialize YouTube client
      const youtubeClient = new YouTubeClient(
        {
          clientId: process.env.GOOGLE_CLIENT_ID!,
          clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
          accessToken: credentials.accessToken,
          refreshToken: credentials.refreshToken,
        },
        this.payload,
      )

      // 5. Find all published/tracked videos with a YouTube videoId
      const videos = await this.payload.find({
        collection: 'youtube-content',
        where: {
          channel: { equals: channelId },
          status: { in: ['published', 'tracked'] },
        },
        limit: 0,
        depth: 0,
      })

      const videosWithYouTubeId = videos.docs.filter(
        (video: any) => video.youtube?.videoId,
      )

      result.skippedCount = videos.docs.length - videosWithYouTubeId.length

      if (videosWithYouTubeId.length === 0) {
        result.success = true
        return result
      }

      // 6. Batch videos into groups of 50 and fetch statistics
      const batches = createBatches(videosWithYouTubeId, YOUTUBE_API_BATCH_LIMIT)

      for (const batch of batches) {
        try {
          const videoIds = batch.map((video: any) => video.youtube.videoId as string)
          const statistics = await youtubeClient.getVideoStatistics(videoIds)

          // Build a lookup map for quick access
          const statsMap = new Map(statistics.map((s) => [s.id, s]))

          // 7. Update each video's performance fields
          for (const video of batch) {
            const youtubeVideoId = (video as any).youtube.videoId as string
            const stats = statsMap.get(youtubeVideoId)

            if (!stats) {
              result.errors.push(
                `No statistics returned for video ${youtubeVideoId} (doc ${video.id})`,
              )
              continue
            }

            try {
              await this.payload.update({
                collection: 'youtube-content',
                id: video.id,
                data: {
                  performance: {
                    views: stats.views,
                    likes: stats.likes,
                    comments: stats.comments,
                    lastSyncedAt: new Date().toISOString(),
                  },
                },
              })
              result.syncedCount++
            } catch (updateError) {
              result.errors.push(
                `Failed to update video ${video.id}: ${updateError}`,
              )
            }
          }
        } catch (batchError) {
          result.errors.push(`Batch API call failed: ${batchError}`)
        }
      }

      result.success = result.errors.length === 0
    } catch (error) {
      result.errors.push(`Sync error: ${error}`)
    }

    return result
  }
}

/**
 * Split an array into chunks of a given size.
 */
function createBatches<T>(items: T[], batchSize: number): T[][] {
  const batches: T[][] = []
  for (let i = 0; i < items.length; i += batchSize) {
    batches.push(items.slice(i, i + batchSize))
  }
  return batches
}

export type { MetricsSyncResult }
