// src/lib/integrations/meta/FacebookClient.ts
// Facebook Client für Page Management, Posts und Kommentare

import { MetaBaseClient, MetaApiError } from './MetaBaseClient'
import type {
  FacebookPage,
  FacebookPost,
  FacebookComment,
  FacebookConversation,
  FacebookMessage,
  FacebookPageInsight,
  MetaPaginatedResponse,
} from '@/types/meta'

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

export interface FacebookPostsOptions {
  /** Maximale Anzahl Posts */
  limit?: number
  /** Filter: published, scheduled, draft */
  filter?: 'published' | 'scheduled' | 'draft'
  /** Nur Posts seit diesem Datum */
  since?: Date
  /** Nur Posts bis zu diesem Datum */
  until?: Date
}

export interface FacebookCommentsOptions {
  /** Maximale Anzahl Kommentare */
  limit?: number
  /** Sortierung: time (älteste zuerst) oder reverse_time (neueste zuerst) */
  order?: 'time' | 'reverse_time'
  /** Filter: toplevel (nur Top-Level), stream (alle inkl. Replies) */
  filter?: 'toplevel' | 'stream'
}

export interface FacebookInsightsOptions {
  /** Metriken die abgefragt werden sollen */
  metrics: string[]
  /** Zeitraum: day, week, days_28 */
  period?: 'day' | 'week' | 'days_28' | 'lifetime'
  /** Startdatum */
  since?: Date
  /** Enddatum */
  until?: Date
}

// =============================================================================
// Facebook Client
// =============================================================================

export class FacebookClient extends MetaBaseClient {
  private pageId: string
  private pageAccessToken: string

  constructor(options: {
    /** User Access Token (Long-lived) */
    userAccessToken: string
    /** Page ID */
    pageId: string
    /** Page Access Token (optional, wird sonst automatisch abgerufen) */
    pageAccessToken?: string
  }) {
    super(options.userAccessToken)
    this.pageId = options.pageId
    this.pageAccessToken = options.pageAccessToken || options.userAccessToken
  }

  // ===========================================================================
  // Page Token Management
  // ===========================================================================

  /**
   * Holt den Page Access Token für die aktuelle Page
   */
  async getPageAccessToken(): Promise<string> {
    const response = await this.request<{ access_token: string }>(`${this.pageId}`, {
      params: {
        fields: 'access_token',
      },
    })
    this.pageAccessToken = response.access_token
    return response.access_token
  }

  /**
   * Setzt den Page Access Token für nachfolgende Requests
   */
  setPageAccessToken(token: string): void {
    this.pageAccessToken = token
  }

  /**
   * Führt einen Request mit dem Page Access Token aus
   */
  private async pageRequest<T>(
    endpoint: string,
    options: {
      method?: 'GET' | 'POST' | 'DELETE'
      params?: Record<string, string | number | boolean | undefined>
      body?: Record<string, unknown>
    } = {}
  ): Promise<T> {
    // Temporär den Access Token auf Page Token setzen
    const originalToken = this.accessToken
    this.accessToken = this.pageAccessToken

    try {
      return await this.request<T>(endpoint, options)
    } finally {
      this.accessToken = originalToken
    }
  }

  // ===========================================================================
  // Posts
  // ===========================================================================

  /**
   * Holt alle Posts einer Page
   */
  async getPosts(options: FacebookPostsOptions = {}): Promise<FacebookPost[]> {
    const { limit = 25, since, until } = options

    const params: Record<string, string | number | boolean | undefined> = {
      fields: [
        'id',
        'message',
        'story',
        'full_picture',
        'permalink_url',
        'created_time',
        'updated_time',
        'shares',
        'reactions.summary(true)',
        'comments.summary(true)',
        'attachments{type,url,media}',
      ].join(','),
      limit,
    }

    if (since) {
      params.since = Math.floor(since.getTime() / 1000)
    }
    if (until) {
      params.until = Math.floor(until.getTime() / 1000)
    }

    const response = await this.pageRequest<MetaPaginatedResponse<FacebookPost>>(
      `${this.pageId}/posts`,
      { params }
    )

    return response.data
  }

  /**
   * Holt einen einzelnen Post mit allen Details
   */
  async getPost(postId: string): Promise<FacebookPost> {
    return this.pageRequest<FacebookPost>(postId, {
      params: {
        fields: [
          'id',
          'message',
          'story',
          'full_picture',
          'permalink_url',
          'created_time',
          'updated_time',
          'shares',
          'reactions.summary(true)',
          'comments.summary(true)',
          'attachments{type,url,media}',
        ].join(','),
      },
    })
  }

  /**
   * Holt alle Posts mit Pagination
   */
  async getAllPosts(options: FacebookPostsOptions = {}): Promise<FacebookPost[]> {
    const { limit = 100, since, until } = options

    const params: Record<string, string | number | boolean | undefined> = {
      fields: [
        'id',
        'message',
        'story',
        'full_picture',
        'permalink_url',
        'created_time',
        'updated_time',
        'shares',
        'reactions.summary(true)',
        'comments.summary(true)',
      ].join(','),
    }

    if (since) {
      params.since = Math.floor(since.getTime() / 1000)
    }
    if (until) {
      params.until = Math.floor(until.getTime() / 1000)
    }

    // Temporär Token wechseln
    const originalToken = this.accessToken
    this.accessToken = this.pageAccessToken

    try {
      return await this.requestPaginated<FacebookPost>(`${this.pageId}/posts`, {
        params,
        limit,
        maxPages: 10,
      })
    } finally {
      this.accessToken = originalToken
    }
  }

  // ===========================================================================
  // Comments
  // ===========================================================================

  /**
   * Holt alle Kommentare eines Posts
   */
  async getPostComments(
    postId: string,
    options: FacebookCommentsOptions = {}
  ): Promise<FacebookComment[]> {
    const { limit = 50, order = 'reverse_time', filter = 'stream' } = options

    const response = await this.pageRequest<MetaPaginatedResponse<FacebookComment>>(
      `${postId}/comments`,
      {
        params: {
          fields: [
            'id',
            'message',
            'from{id,name}',
            'created_time',
            'like_count',
            'comment_count',
            'is_hidden',
            'can_hide',
            'can_reply_privately',
            'parent{id}',
            'attachment{type,url,media}',
          ].join(','),
          order,
          filter,
          limit,
        },
      }
    )

    return response.data
  }

  /**
   * Holt alle Kommentare eines Posts mit Pagination
   */
  async getAllPostComments(
    postId: string,
    options: FacebookCommentsOptions = {}
  ): Promise<FacebookComment[]> {
    const { limit = 100, order = 'reverse_time', filter = 'stream' } = options

    const originalToken = this.accessToken
    this.accessToken = this.pageAccessToken

    try {
      return await this.requestPaginated<FacebookComment>(`${postId}/comments`, {
        params: {
          fields: [
            'id',
            'message',
            'from{id,name}',
            'created_time',
            'like_count',
            'comment_count',
            'is_hidden',
            'can_hide',
            'parent{id}',
          ].join(','),
          order,
          filter,
        },
        limit,
        maxPages: 10,
      })
    } finally {
      this.accessToken = originalToken
    }
  }

  /**
   * Holt einen einzelnen Kommentar mit Details
   */
  async getComment(commentId: string): Promise<FacebookComment> {
    return this.pageRequest<FacebookComment>(commentId, {
      params: {
        fields: [
          'id',
          'message',
          'from{id,name}',
          'created_time',
          'like_count',
          'comment_count',
          'is_hidden',
          'can_hide',
          'can_reply_privately',
          'parent{id}',
          'attachment{type,url,media}',
        ].join(','),
      },
    })
  }

  /**
   * Antwortet auf einen Kommentar
   */
  async replyToComment(commentId: string, message: string): Promise<{ id: string }> {
    return this.pageRequest<{ id: string }>(`${commentId}/comments`, {
      method: 'POST',
      body: { message },
    })
  }

  /**
   * Versteckt einen Kommentar
   */
  async hideComment(commentId: string): Promise<{ success: boolean }> {
    return this.pageRequest<{ success: boolean }>(commentId, {
      method: 'POST',
      body: { is_hidden: true },
    })
  }

  /**
   * Zeigt einen versteckten Kommentar wieder an
   */
  async unhideComment(commentId: string): Promise<{ success: boolean }> {
    return this.pageRequest<{ success: boolean }>(commentId, {
      method: 'POST',
      body: { is_hidden: false },
    })
  }

  /**
   * Löscht einen Kommentar
   */
  async deleteComment(commentId: string): Promise<{ success: boolean }> {
    return this.pageRequest<{ success: boolean }>(commentId, {
      method: 'DELETE',
    })
  }

  /**
   * Liked einen Kommentar (als Page)
   */
  async likeComment(commentId: string): Promise<{ success: boolean }> {
    return this.pageRequest<{ success: boolean }>(`${commentId}/likes`, {
      method: 'POST',
    })
  }

  /**
   * Entfernt Like von einem Kommentar
   */
  async unlikeComment(commentId: string): Promise<{ success: boolean }> {
    return this.pageRequest<{ success: boolean }>(`${commentId}/likes`, {
      method: 'DELETE',
    })
  }

  // ===========================================================================
  // Conversations (Messenger)
  // ===========================================================================

  /**
   * Holt alle Conversations der Page
   */
  async getConversations(limit: number = 25): Promise<FacebookConversation[]> {
    const response = await this.pageRequest<MetaPaginatedResponse<FacebookConversation>>(
      `${this.pageId}/conversations`,
      {
        params: {
          fields: [
            'id',
            'participants{id,name,email}',
            'updated_time',
            'message_count',
            'unread_count',
            'can_reply',
          ].join(','),
          limit,
        },
      }
    )

    return response.data
  }

  /**
   * Holt Nachrichten einer Conversation
   */
  async getConversationMessages(
    conversationId: string,
    limit: number = 25
  ): Promise<FacebookMessage[]> {
    const response = await this.pageRequest<MetaPaginatedResponse<FacebookMessage>>(
      `${conversationId}/messages`,
      {
        params: {
          fields: [
            'id',
            'message',
            'from{id,name,email}',
            'to{id,name}',
            'created_time',
            'attachments{id,mime_type,name,file_url,image_data}',
          ].join(','),
          limit,
        },
      }
    )

    return response.data
  }

  /**
   * Sendet eine Nachricht in einer Conversation
   */
  async sendMessage(
    recipientId: string,
    message: string
  ): Promise<{ recipient_id: string; message_id: string }> {
    return this.pageRequest<{ recipient_id: string; message_id: string }>(
      `${this.pageId}/messages`,
      {
        method: 'POST',
        body: {
          recipient: { id: recipientId },
          message: { text: message },
        },
      }
    )
  }

  // ===========================================================================
  // Page Insights
  // ===========================================================================

  /**
   * Holt Page Insights/Analytics
   */
  async getPageInsights(options: FacebookInsightsOptions): Promise<FacebookPageInsight[]> {
    const { metrics, period = 'day', since, until } = options

    const params: Record<string, string | number | boolean | undefined> = {
      metric: metrics.join(','),
      period,
    }

    if (since) {
      params.since = Math.floor(since.getTime() / 1000)
    }
    if (until) {
      params.until = Math.floor(until.getTime() / 1000)
    }

    const response = await this.pageRequest<{ data: FacebookPageInsight[] }>(
      `${this.pageId}/insights`,
      { params }
    )

    return response.data
  }

  /**
   * Holt Standard Page Insights (Impressions, Reach, Engagement)
   */
  async getStandardInsights(
    since?: Date,
    until?: Date
  ): Promise<{
    impressions: number
    reach: number
    engagedUsers: number
    newFans: number
  }> {
    const insights = await this.getPageInsights({
      metrics: [
        'page_impressions',
        'page_post_engagements',
        'page_fan_adds',
        'page_engaged_users',
      ],
      period: 'day',
      since,
      until,
    })

    const getValue = (name: string): number => {
      const insight = insights.find((i) => i.name === name)
      if (!insight?.values?.[0]) return 0
      const value = insight.values[0].value
      return typeof value === 'number' ? value : 0
    }

    return {
      impressions: getValue('page_impressions'),
      reach: getValue('page_post_engagements'),
      engagedUsers: getValue('page_engaged_users'),
      newFans: getValue('page_fan_adds'),
    }
  }

  // ===========================================================================
  // Utility Methods
  // ===========================================================================

  /**
   * Prüft ob die Page verbunden ist und Zugriffsrechte hat
   */
  async verifyPageAccess(): Promise<{
    isValid: boolean
    pageName?: string
    permissions?: string[]
  }> {
    try {
      const page = await this.pageRequest<FacebookPage>(`${this.pageId}`, {
        params: {
          fields: 'id,name,tasks',
        },
      })

      return {
        isValid: true,
        pageName: page.name,
        permissions: page.tasks,
      }
    } catch (error) {
      if (error instanceof MetaApiError) {
        return {
          isValid: false,
        }
      }
      throw error
    }
  }

  /**
   * Holt alle ungelesenen Aktivitäten (Kommentare + Nachrichten)
   */
  async getUnreadActivity(): Promise<{
    unreadComments: number
    unreadMessages: number
  }> {
    // Ungelesene Conversations zählen
    const conversations = await this.getConversations(100)
    const unreadMessages = conversations.reduce((sum, conv) => sum + (conv.unread_count || 0), 0)

    // Für Kommentare gibt es keine direkte "unread" API
    // Dies müsste über die Datenbank/Sync getracked werden
    return {
      unreadComments: 0, // Muss über eigenen Sync-Status getracked werden
      unreadMessages,
    }
  }
}

export default FacebookClient
