// src/lib/integrations/youtube/VideoUploadService.ts

import fs from 'fs'
import path from 'path'

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

interface VideoMetadata {
  title: string
  description: string
  tags: string[]
  visibility: 'public' | 'unlisted' | 'private'
  categoryId?: string
}

interface UploadOptions {
  mediaId: number
  metadata: VideoMetadata
  scheduledPublishAt?: string
}

interface UploadResult {
  success: boolean
  youtubeVideoId?: string
  youtubeUrl?: string
  error?: string
}

/**
 * Uploads videos to YouTube via the Data API v3.
 *
 * Reads video files from the Payload media collection, resolves OAuth credentials
 * from the social-accounts collection, and calls youtube.videos.insert().
 */
export class VideoUploadService {
  private payload: Payload

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

  /**
   * Upload a video file from the media collection to YouTube.
   *
   * When scheduledPublishAt is provided, the video is uploaded as private
   * with a publishAt timestamp so YouTube publishes it automatically.
   */
  async uploadVideo(options: UploadOptions): Promise<UploadResult> {
    const { mediaId, metadata, scheduledPublishAt } = options

    // 1. Resolve OAuth credentials from social-accounts
    const credentials = await this.loadCredentials()
    if (!credentials) {
      return {
        success: false,
        error: 'No active YouTube social account with valid credentials found',
      }
    }

    // 2. Load the media document
    const media = await this.payload.findByID({
      collection: 'media',
      id: mediaId,
      depth: 0,
    })

    if (!media) {
      return { success: false, error: `Media with ID ${mediaId} not found` }
    }

    const filename = media.filename as string | undefined
    if (!filename) {
      return {
        success: false,
        error: `Media ${mediaId} has no filename`,
      }
    }

    // 3. Verify the file exists on disk
    const filePath = path.join(process.cwd(), 'media', filename)
    if (!fs.existsSync(filePath)) {
      return {
        success: false,
        error: `File not found on disk: ${filePath}`,
      }
    }

    // 4. Build the OAuth2 client
    const oauth2Client = new google.auth.OAuth2(
      process.env.GOOGLE_CLIENT_ID,
      process.env.GOOGLE_CLIENT_SECRET,
    )
    oauth2Client.setCredentials({
      access_token: credentials.accessToken,
      refresh_token: credentials.refreshToken,
    })

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

    // 5. Determine privacy status and optional scheduled publish time
    let privacyStatus: string = metadata.visibility
    let publishAt: string | undefined

    if (scheduledPublishAt) {
      privacyStatus = 'private'
      publishAt = scheduledPublishAt
    }

    // 6. Execute the upload
    try {
      const response = await youtube.videos.insert({
        part: ['snippet', 'status'],
        requestBody: {
          snippet: {
            title: metadata.title,
            description: metadata.description,
            tags: metadata.tags,
            categoryId: metadata.categoryId,
          },
          status: {
            privacyStatus,
            ...(publishAt ? { publishAt } : {}),
          },
        },
        media: {
          body: fs.createReadStream(filePath),
        },
      })

      const videoId = response.data.id
      if (!videoId) {
        return {
          success: false,
          error: 'YouTube API returned no video ID',
        }
      }

      return {
        success: true,
        youtubeVideoId: videoId,
        youtubeUrl: `https://www.youtube.com/watch?v=${videoId}`,
      }
    } catch (error) {
      const message = error instanceof Error ? error.message : String(error)
      return { success: false, error: `YouTube upload failed: ${message}` }
    }
  }

  /**
   * Find the first active YouTube social account with valid credentials.
   */
  private async loadCredentials(): Promise<{
    accessToken: string
    refreshToken: string
  } | null> {
    const platforms = await this.payload.find({
      collection: 'social-platforms',
      where: { slug: { equals: 'youtube' } },
      limit: 1,
      depth: 0,
    })

    const platformId = platforms.docs[0]?.id
    if (!platformId) return null

    const accounts = await this.payload.find({
      collection: 'social-accounts',
      where: {
        platform: { equals: platformId },
        isActive: { equals: true },
      },
      limit: 1,
      depth: 0,
    })

    const account = accounts.docs[0]
    if (!account) return null

    const creds = account.credentials as {
      accessToken?: string
      refreshToken?: string
    } | undefined

    if (!creds?.accessToken || !creds?.refreshToken) return null

    return {
      accessToken: creds.accessToken,
      refreshToken: creds.refreshToken,
    }
  }
}

export type { VideoMetadata, UploadOptions, UploadResult }
