// src/lib/jobs/UnifiedSyncService.ts
// Unified Sync Service für alle Social Media Plattformen

import { getPayload, Payload } from 'payload'
import config from '@payload-config'
import { CommentsSyncService } from '../integrations/youtube/CommentsSyncService'
import { FacebookSyncService } from '../integrations/meta/FacebookSyncService'
import { InstagramSyncService } from '../integrations/meta/InstagramSyncService'
import { JobLogger } from './JobLogger'

// =============================================================================
// Types
// =============================================================================

export type SupportedPlatform = 'youtube' | 'facebook' | 'instagram'

export interface PlatformSyncResult {
  platform: SupportedPlatform
  accountId: number
  accountName: string
  success: boolean
  newComments: number
  updatedComments: number
  newMessages: number
  postsProcessed: number
  errors: string[]
  duration: number
}

export interface UnifiedSyncResult {
  success: boolean
  startedAt: Date
  completedAt: Date
  duration: number
  platforms: {
    [key in SupportedPlatform]?: {
      accountsProcessed: number
      totalNewComments: number
      totalUpdatedComments: number
      totalErrors: number
    }
  }
  results: PlatformSyncResult[]
  errors: string[]
}

export interface UnifiedSyncOptions {
  /** Nur bestimmte Plattformen synchronisieren */
  platforms?: SupportedPlatform[]
  /** Nur bestimmte Account-IDs synchronisieren */
  accountIds?: number[]
  /** AI-Analyse aktivieren */
  analyzeWithAI?: boolean
  /** Maximale Items pro Account */
  maxItemsPerAccount?: number
  /** Nur seit diesem Datum synchronisieren */
  sinceDate?: Date
}

export interface SyncStatus {
  isRunning: boolean
  currentPlatform: SupportedPlatform | null
  currentAccount: string | null
  progress: {
    totalAccounts: number
    processedAccounts: number
    percentage: number
  }
  lastRunAt: string | null
  lastResult: UnifiedSyncResult | null
}

// =============================================================================
// Global State
// =============================================================================

let syncStatus: SyncStatus = {
  isRunning: false,
  currentPlatform: null,
  currentAccount: null,
  progress: {
    totalAccounts: 0,
    processedAccounts: 0,
    percentage: 0,
  },
  lastRunAt: null,
  lastResult: null,
}

// =============================================================================
// Platform Detection
// =============================================================================

function detectPlatform(platformDoc: any): SupportedPlatform | null {
  const slug = platformDoc?.slug?.toLowerCase()
  const apiType = platformDoc?.apiConfig?.apiType

  if (slug === 'youtube' || apiType === 'youtube_v3') {
    return 'youtube'
  }
  if (slug === 'facebook' || apiType === 'facebook_graph' || apiType === 'meta_graph') {
    return 'facebook'
  }
  if (slug === 'instagram' || apiType === 'instagram_graph') {
    return 'instagram'
  }

  return null
}

// =============================================================================
// Unified Sync Service
// =============================================================================

export class UnifiedSyncService {
  private payload: Payload
  private logger: JobLogger
  private youtubeSyncService: CommentsSyncService
  private facebookSyncService: FacebookSyncService
  private instagramSyncService: InstagramSyncService

  constructor(payload: Payload) {
    this.payload = payload
    this.logger = new JobLogger('unified-sync')
    this.youtubeSyncService = new CommentsSyncService(payload)
    this.facebookSyncService = new FacebookSyncService(payload)
    this.instagramSyncService = new InstagramSyncService(payload)
  }

  /**
   * Führt einen vollständigen Sync aller Plattformen durch
   */
  async runFullSync(options: UnifiedSyncOptions = {}): Promise<UnifiedSyncResult> {
    const {
      platforms,
      accountIds,
      analyzeWithAI = true,
      maxItemsPerAccount = 100,
      sinceDate,
    } = options

    const startedAt = new Date()
    const results: PlatformSyncResult[] = []
    const errors: string[] = []

    // Prüfen ob bereits ein Sync läuft
    if (syncStatus.isRunning) {
      return {
        success: false,
        startedAt,
        completedAt: new Date(),
        duration: 0,
        platforms: {},
        results: [],
        errors: ['Sync already running'],
      }
    }

    syncStatus.isRunning = true
    syncStatus.progress = { totalAccounts: 0, processedAccounts: 0, percentage: 0 }

    try {
      this.logger.info('Starting unified sync', { platforms, accountIds })

      // Alle aktiven Accounts laden
      const accounts = await this.loadActiveAccounts(platforms, accountIds)
      syncStatus.progress.totalAccounts = accounts.length

      this.logger.info(`Found ${accounts.length} active accounts to sync`)

      if (accounts.length === 0) {
        return this.createResult(startedAt, results, errors)
      }

      // Accounts nach Plattform gruppieren
      const accountsByPlatform = this.groupAccountsByPlatform(accounts)

      // Jede Plattform synchronisieren
      for (const [platform, platformAccounts] of Object.entries(accountsByPlatform)) {
        syncStatus.currentPlatform = platform as SupportedPlatform

        for (const account of platformAccounts) {
          syncStatus.currentAccount = account.displayName || `Account ${account.id}`

          try {
            const result = await this.syncAccount(
              platform as SupportedPlatform,
              account,
              {
                analyzeWithAI,
                maxItems: maxItemsPerAccount,
                sinceDate,
              }
            )
            results.push(result)
          } catch (error) {
            const errorMsg = error instanceof Error ? error.message : String(error)
            errors.push(`${platform}/${account.id}: ${errorMsg}`)
            this.logger.error(`Failed to sync account ${account.id}`, error)
          }

          syncStatus.progress.processedAccounts++
          syncStatus.progress.percentage = Math.round(
            (syncStatus.progress.processedAccounts / syncStatus.progress.totalAccounts) * 100
          )

          // Rate Limiting zwischen Accounts
          await this.sleep(500)
        }
      }

      const finalResult = this.createResult(startedAt, results, errors)
      syncStatus.lastResult = finalResult
      syncStatus.lastRunAt = startedAt.toISOString()

      this.logger.summary({
        success: finalResult.success,
        processed: results.length,
        errors: errors.length,
      })

      return finalResult
    } catch (error) {
      const errorMsg = error instanceof Error ? error.message : String(error)
      this.logger.error('Unified sync failed', error)
      errors.push(errorMsg)
      return this.createResult(startedAt, results, errors)
    } finally {
      syncStatus.isRunning = false
      syncStatus.currentPlatform = null
      syncStatus.currentAccount = null
    }
  }

  /**
   * Lädt alle aktiven Social Accounts
   */
  private async loadActiveAccounts(
    platforms?: SupportedPlatform[],
    accountIds?: number[]
  ): Promise<any[]> {
    const where: any = {
      and: [{ isActive: { equals: true } }],
    }

    // Account-ID Filter
    if (accountIds && accountIds.length > 0) {
      where.and.push({
        id: { in: accountIds },
      })
    }

    const accounts = await this.payload.find({
      collection: 'social-accounts',
      where,
      limit: 100,
      depth: 2,
    })

    // Plattform-Filter anwenden
    if (platforms && platforms.length > 0) {
      return accounts.docs.filter((account) => {
        const platform = detectPlatform(account.platform)
        return platform && platforms.includes(platform)
      })
    }

    // Nur Accounts mit unterstützter Plattform zurückgeben
    return accounts.docs.filter((account) => {
      const platform = detectPlatform(account.platform)
      return platform !== null
    })
  }

  /**
   * Gruppiert Accounts nach Plattform
   */
  private groupAccountsByPlatform(accounts: any[]): Record<SupportedPlatform, any[]> {
    const grouped: Record<SupportedPlatform, any[]> = {
      youtube: [],
      facebook: [],
      instagram: [],
    }

    for (const account of accounts) {
      const platform = detectPlatform(account.platform)
      if (platform) {
        grouped[platform].push(account)
      }
    }

    return grouped
  }

  /**
   * Synchronisiert einen einzelnen Account
   */
  private async syncAccount(
    platform: SupportedPlatform,
    account: any,
    options: {
      analyzeWithAI: boolean
      maxItems: number
      sinceDate?: Date
    }
  ): Promise<PlatformSyncResult> {
    const { analyzeWithAI, maxItems, sinceDate } = options
    const accountId = account.id as number
    const accountName = (account.displayName as string) || `Account ${accountId}`
    const startTime = Date.now()

    this.logger.info(`Syncing ${platform} account: ${accountName}`)

    // Default since date: letzte 7 Tage oder letzter Sync
    const stats = account.stats as { lastSyncedAt?: string } | undefined
    const effectiveSinceDate =
      sinceDate ||
      (stats?.lastSyncedAt
        ? new Date(stats.lastSyncedAt)
        : new Date(Date.now() - 7 * 24 * 60 * 60 * 1000))

    try {
      let result: PlatformSyncResult

      switch (platform) {
        case 'youtube':
          result = await this.syncYouTubeAccount(accountId, accountName, {
            sinceDate: effectiveSinceDate,
            maxItems,
            analyzeWithAI,
          })
          break

        case 'facebook':
          result = await this.syncFacebookAccount(accountId, accountName, {
            sinceDate: effectiveSinceDate,
            maxItems,
            analyzeWithAI,
          })
          break

        case 'instagram':
          result = await this.syncInstagramAccount(accountId, accountName, {
            sinceDate: effectiveSinceDate,
            maxItems,
            analyzeWithAI,
          })
          break

        default:
          throw new Error(`Unsupported platform: ${platform}`)
      }

      result.duration = Date.now() - startTime

      this.logger.info(
        `${platform}/${accountName}: ${result.newComments} new, ${result.updatedComments} updated`
      )

      return result
    } catch (error) {
      const errorMsg = error instanceof Error ? error.message : String(error)
      return {
        platform,
        accountId,
        accountName,
        success: false,
        newComments: 0,
        updatedComments: 0,
        newMessages: 0,
        postsProcessed: 0,
        errors: [errorMsg],
        duration: Date.now() - startTime,
      }
    }
  }

  /**
   * YouTube Account synchronisieren
   */
  private async syncYouTubeAccount(
    accountId: number,
    accountName: string,
    options: { sinceDate: Date; maxItems: number; analyzeWithAI: boolean }
  ): Promise<PlatformSyncResult> {
    const syncResult = await this.youtubeSyncService.syncComments({
      socialAccountId: accountId,
      sinceDate: options.sinceDate,
      maxComments: options.maxItems,
      analyzeWithAI: options.analyzeWithAI,
    })

    return {
      platform: 'youtube',
      accountId,
      accountName,
      success: syncResult.success,
      newComments: syncResult.newComments,
      updatedComments: syncResult.updatedComments,
      newMessages: 0,
      postsProcessed: 0,
      errors: syncResult.errors,
      duration: 0,
    }
  }

  /**
   * Facebook Account synchronisieren
   */
  private async syncFacebookAccount(
    accountId: number,
    accountName: string,
    options: { sinceDate: Date; maxItems: number; analyzeWithAI: boolean }
  ): Promise<PlatformSyncResult> {
    const syncResult = await this.facebookSyncService.syncComments({
      socialAccountId: accountId,
      sinceDate: options.sinceDate,
      maxItems: options.maxItems,
      analyzeWithAI: options.analyzeWithAI,
      syncComments: true,
      syncMessages: false,
    })

    return {
      platform: 'facebook',
      accountId,
      accountName,
      success: syncResult.errors.length === 0,
      newComments: syncResult.newComments,
      updatedComments: syncResult.updatedComments,
      newMessages: syncResult.newMessages,
      postsProcessed: syncResult.postsProcessed,
      errors: syncResult.errors,
      duration: syncResult.duration,
    }
  }

  /**
   * Instagram Account synchronisieren
   */
  private async syncInstagramAccount(
    accountId: number,
    accountName: string,
    options: { sinceDate: Date; maxItems: number; analyzeWithAI: boolean }
  ): Promise<PlatformSyncResult> {
    const syncResult = await this.instagramSyncService.syncComments({
      socialAccountId: accountId,
      sinceDate: options.sinceDate,
      maxItems: options.maxItems,
      analyzeWithAI: options.analyzeWithAI,
      syncComments: true,
      syncMentions: true,
    })

    return {
      platform: 'instagram',
      accountId,
      accountName,
      success: syncResult.errors.length === 0,
      newComments: syncResult.newComments,
      updatedComments: syncResult.updatedComments,
      newMessages: syncResult.newMessages,
      postsProcessed: syncResult.postsProcessed,
      errors: syncResult.errors,
      duration: syncResult.duration,
    }
  }

  /**
   * Erstellt das finale Sync-Ergebnis
   */
  private createResult(
    startedAt: Date,
    results: PlatformSyncResult[],
    errors: string[]
  ): UnifiedSyncResult {
    const completedAt = new Date()

    // Ergebnisse nach Plattform aggregieren
    const platforms: UnifiedSyncResult['platforms'] = {}

    for (const result of results) {
      if (!platforms[result.platform]) {
        platforms[result.platform] = {
          accountsProcessed: 0,
          totalNewComments: 0,
          totalUpdatedComments: 0,
          totalErrors: 0,
        }
      }

      platforms[result.platform]!.accountsProcessed++
      platforms[result.platform]!.totalNewComments += result.newComments
      platforms[result.platform]!.totalUpdatedComments += result.updatedComments
      platforms[result.platform]!.totalErrors += result.errors.length
    }

    return {
      success: errors.length === 0 && results.every((r) => r.success),
      startedAt,
      completedAt,
      duration: completedAt.getTime() - startedAt.getTime(),
      platforms,
      results,
      errors,
    }
  }

  private sleep(ms: number): Promise<void> {
    return new Promise((resolve) => setTimeout(resolve, ms))
  }
}

// =============================================================================
// Convenience Functions
// =============================================================================

/**
 * Führt einen vollständigen Sync aus (Singleton-Pattern)
 */
export async function runUnifiedSync(
  options: UnifiedSyncOptions = {}
): Promise<UnifiedSyncResult> {
  const payload = await getPayload({ config })
  const service = new UnifiedSyncService(payload)
  return service.runFullSync(options)
}

/**
 * Gibt den aktuellen Sync-Status zurück
 */
export function getUnifiedSyncStatus(): SyncStatus {
  return { ...syncStatus }
}

/**
 * Setzt den Sync-Status zurück (für Tests)
 */
export function resetUnifiedSyncStatus(): void {
  syncStatus = {
    isRunning: false,
    currentPlatform: null,
    currentAccount: null,
    progress: {
      totalAccounts: 0,
      processedAccounts: 0,
      percentage: 0,
    },
    lastRunAt: null,
    lastResult: null,
  }
}

export default UnifiedSyncService
