// src/lib/integrations/meta/InstagramClient.ts
// Instagram Client für Business Account Management

import { MetaBaseClient, MetaApiError } from './MetaBaseClient'
import type {
  InstagramBusinessAccount,
  InstagramMedia,
  InstagramComment,
  InstagramMention,
  InstagramStoryMention,
  InstagramConversation,
  InstagramMessage,
  InstagramInsight,
  MetaPaginatedResponse,
} from '@/types/meta'

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

export interface InstagramMediaOptions {
  /** Maximale Anzahl Media */
  limit?: number
  /** Nur bestimmte Media-Typen */
  mediaType?: 'IMAGE' | 'VIDEO' | 'CAROUSEL_ALBUM' | 'REELS'
  /** Nur Media seit diesem Datum */
  since?: Date
}

export interface InstagramCommentsOptions {
  /** Maximale Anzahl Kommentare */
  limit?: number
}

export interface InstagramInsightsOptions {
  /** Metriken für Account Insights */
  metrics: string[]
  /** Zeitraum */
  period?: 'day' | 'week' | 'days_28' | 'lifetime'
  /** Startdatum */
  since?: Date
  /** Enddatum */
  until?: Date
}

export interface InstagramMediaInsightsOptions {
  /** Metriken für Media Insights */
  metrics: string[]
}

// =============================================================================
// Instagram Client
// =============================================================================

export class InstagramClient extends MetaBaseClient {
  private instagramAccountId: string
  private pageAccessToken: string

  constructor(options: {
    /** Page Access Token (mit Instagram-Berechtigung) */
    pageAccessToken: string
    /** Instagram Business Account ID */
    instagramAccountId: string
  }) {
    super(options.pageAccessToken)
    this.instagramAccountId = options.instagramAccountId
    this.pageAccessToken = options.pageAccessToken
  }

  // ===========================================================================
  // Account Info
  // ===========================================================================

  /**
   * Holt Informationen über den Instagram Business Account
   */
  async getAccountInfo(): Promise<InstagramBusinessAccount> {
    return this.request<InstagramBusinessAccount>(this.instagramAccountId, {
      params: {
        fields: [
          'id',
          'username',
          'name',
          'profile_picture_url',
          'followers_count',
          'follows_count',
          'media_count',
          'biography',
          'website',
        ].join(','),
      },
    })
  }

  // ===========================================================================
  // Media
  // ===========================================================================

  /**
   * Holt alle Media (Posts) des Accounts
   */
  async getMedia(options: InstagramMediaOptions = {}): Promise<InstagramMedia[]> {
    const { limit = 25 } = options

    const response = await this.request<MetaPaginatedResponse<InstagramMedia>>(
      `${this.instagramAccountId}/media`,
      {
        params: {
          fields: [
            'id',
            'media_type',
            'media_url',
            'thumbnail_url',
            'permalink',
            'caption',
            'timestamp',
            'like_count',
            'comments_count',
            'children{id,media_type,media_url}',
          ].join(','),
          limit,
        },
      }
    )

    return response.data
  }

  /**
   * Holt alle Media mit Pagination
   */
  async getAllMedia(options: InstagramMediaOptions = {}): Promise<InstagramMedia[]> {
    const { limit = 50 } = options

    return this.requestPaginated<InstagramMedia>(`${this.instagramAccountId}/media`, {
      params: {
        fields: [
          'id',
          'media_type',
          'media_url',
          'thumbnail_url',
          'permalink',
          'caption',
          'timestamp',
          'like_count',
          'comments_count',
        ].join(','),
      },
      limit,
      maxPages: 10,
    })
  }

  /**
   * Holt ein einzelnes Media mit Details
   */
  async getMediaById(mediaId: string): Promise<InstagramMedia> {
    return this.request<InstagramMedia>(mediaId, {
      params: {
        fields: [
          'id',
          'media_type',
          'media_url',
          'thumbnail_url',
          'permalink',
          'caption',
          'timestamp',
          'like_count',
          'comments_count',
          'children{id,media_type,media_url}',
        ].join(','),
      },
    })
  }

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

  /**
   * Holt alle Kommentare eines Media
   */
  async getMediaComments(
    mediaId: string,
    options: InstagramCommentsOptions = {}
  ): Promise<InstagramComment[]> {
    const { limit = 50 } = options

    const response = await this.request<MetaPaginatedResponse<InstagramComment>>(
      `${mediaId}/comments`,
      {
        params: {
          fields: [
            'id',
            'text',
            'username',
            'timestamp',
            'like_count',
            'replies{id,text,username,timestamp,like_count}',
            'from{id,username}',
            'hidden',
          ].join(','),
          limit,
        },
      }
    )

    return response.data
  }

  /**
   * Holt alle Kommentare mit Pagination
   */
  async getAllMediaComments(
    mediaId: string,
    options: InstagramCommentsOptions = {}
  ): Promise<InstagramComment[]> {
    const { limit = 100 } = options

    return this.requestPaginated<InstagramComment>(`${mediaId}/comments`, {
      params: {
        fields: [
          'id',
          'text',
          'username',
          'timestamp',
          'like_count',
          'from{id,username}',
          'hidden',
        ].join(','),
      },
      limit,
      maxPages: 5,
    })
  }

  /**
   * Holt einen einzelnen Kommentar
   */
  async getComment(commentId: string): Promise<InstagramComment> {
    return this.request<InstagramComment>(commentId, {
      params: {
        fields: [
          'id',
          'text',
          'username',
          'timestamp',
          'like_count',
          'replies{id,text,username,timestamp,like_count}',
          'from{id,username}',
          'hidden',
        ].join(','),
      },
    })
  }

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

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

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

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

  // ===========================================================================
  // Mentions
  // ===========================================================================

  /**
   * Holt alle Mentions (Posts in denen der Account getaggt wurde)
   */
  async getMentions(limit: number = 25): Promise<InstagramMention[]> {
    try {
      const response = await this.request<MetaPaginatedResponse<InstagramMention>>(
        `${this.instagramAccountId}/tags`,
        {
          params: {
            fields: [
              'id',
              'caption',
              'media_type',
              'media_url',
              'permalink',
              'timestamp',
              'username',
              'comments_count',
              'like_count',
            ].join(','),
            limit,
          },
        }
      )

      return response.data
    } catch (error) {
      // Tags-Endpoint benötigt spezielle Berechtigung
      if (error instanceof MetaApiError && error.isPermissionError()) {
        console.warn('[InstagramClient] No permission for tags endpoint')
        return []
      }
      throw error
    }
  }

  /**
   * Holt Story-Mentions (Stories in denen der Account getaggt wurde)
   * WICHTIG: Stories verschwinden nach 24h!
   */
  async getStoryMentions(limit: number = 25): Promise<InstagramStoryMention[]> {
    try {
      const response = await this.request<MetaPaginatedResponse<InstagramStoryMention>>(
        `${this.instagramAccountId}/stories`,
        {
          params: {
            fields: ['id', 'media_type', 'media_url', 'timestamp'].join(','),
            limit,
          },
        }
      )

      return response.data
    } catch (error) {
      // Stories-Endpoint benötigt spezielle Berechtigung
      if (error instanceof MetaApiError && error.isPermissionError()) {
        console.warn('[InstagramClient] No permission for stories endpoint')
        return []
      }
      throw error
    }
  }

  // ===========================================================================
  // Conversations (Instagram Direct)
  // ===========================================================================

  /**
   * Holt alle Instagram Direct Conversations
   * Benötigt instagram_manage_messages Berechtigung
   */
  async getConversations(limit: number = 25): Promise<InstagramConversation[]> {
    try {
      const response = await this.request<MetaPaginatedResponse<InstagramConversation>>(
        `${this.instagramAccountId}/conversations`,
        {
          params: {
            fields: [
              'id',
              'participants{id,username}',
              'updated_time',
              'messages{id,message,from,created_time}',
            ].join(','),
            limit,
          },
        }
      )

      return response.data
    } catch (error) {
      if (error instanceof MetaApiError && error.isPermissionError()) {
        console.warn('[InstagramClient] No permission for conversations endpoint')
        return []
      }
      throw error
    }
  }

  /**
   * Holt Nachrichten einer Conversation
   */
  async getConversationMessages(
    conversationId: string,
    limit: number = 25
  ): Promise<InstagramMessage[]> {
    const response = await this.request<MetaPaginatedResponse<InstagramMessage>>(
      `${conversationId}/messages`,
      {
        params: {
          fields: [
            'id',
            'message',
            'from{id,username}',
            'created_time',
            'attachments{type,url}',
          ].join(','),
          limit,
        },
      }
    )

    return response.data
  }

  /**
   * Sendet eine Nachricht
   * Benötigt instagram_manage_messages Berechtigung
   */
  async sendMessage(
    recipientId: string,
    message: string
  ): Promise<{ recipient_id: string; message_id: string }> {
    return this.request<{ recipient_id: string; message_id: string }>(
      `${this.instagramAccountId}/messages`,
      {
        method: 'POST',
        body: {
          recipient: { id: recipientId },
          message: { text: message },
        },
      }
    )
  }

  // ===========================================================================
  // Insights
  // ===========================================================================

  /**
   * Holt Account Insights
   */
  async getAccountInsights(options: InstagramInsightsOptions): Promise<InstagramInsight[]> {
    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.request<{ data: InstagramInsight[] }>(
      `${this.instagramAccountId}/insights`,
      { params }
    )

    return response.data
  }

  /**
   * Holt Standard Account Insights (Impressions, Reach, Profile Views)
   */
  async getStandardInsights(
    since?: Date,
    until?: Date
  ): Promise<{
    impressions: number
    reach: number
    profileViews: number
    websiteClicks: number
  }> {
    const insights = await this.getAccountInsights({
      metrics: ['impressions', 'reach', 'profile_views', 'website_clicks'],
      period: 'day',
      since,
      until,
    })

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

    return {
      impressions: getValue('impressions'),
      reach: getValue('reach'),
      profileViews: getValue('profile_views'),
      websiteClicks: getValue('website_clicks'),
    }
  }

  /**
   * Holt Insights für ein einzelnes Media
   */
  async getMediaInsights(
    mediaId: string,
    options: InstagramMediaInsightsOptions
  ): Promise<InstagramInsight[]> {
    const { metrics } = options

    const response = await this.request<{ data: InstagramInsight[] }>(`${mediaId}/insights`, {
      params: {
        metric: metrics.join(','),
      },
    })

    return response.data
  }

  /**
   * Holt Standard Media Insights (Impressions, Reach, Engagement)
   */
  async getStandardMediaInsights(mediaId: string): Promise<{
    impressions: number
    reach: number
    engagement: number
    saved: number
  }> {
    try {
      const insights = await this.getMediaInsights(mediaId, {
        metrics: ['impressions', 'reach', 'engagement', 'saved'],
      })

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

      return {
        impressions: getValue('impressions'),
        reach: getValue('reach'),
        engagement: getValue('engagement'),
        saved: getValue('saved'),
      }
    } catch (error) {
      // Media Insights sind nicht für alle Media-Typen verfügbar
      if (error instanceof MetaApiError) {
        return { impressions: 0, reach: 0, engagement: 0, saved: 0 }
      }
      throw error
    }
  }

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

  /**
   * Prüft ob der Account verbunden ist und Zugriffsrechte hat
   */
  async verifyAccountAccess(): Promise<{
    isValid: boolean
    username?: string
    followersCount?: number
  }> {
    try {
      const account = await this.getAccountInfo()

      return {
        isValid: true,
        username: account.username,
        followersCount: account.followers_count,
      }
    } catch (error) {
      if (error instanceof MetaApiError) {
        return { isValid: false }
      }
      throw error
    }
  }

  /**
   * Holt zusammengefasste Statistiken für den Account
   */
  async getAccountStats(): Promise<{
    followers: number
    following: number
    mediaCount: number
    recentEngagement: number
  }> {
    const account = await this.getAccountInfo()

    // Berechne Engagement der letzten Posts
    let recentEngagement = 0
    try {
      const recentMedia = await this.getMedia({ limit: 10 })
      recentEngagement = recentMedia.reduce((sum, media) => {
        return sum + (media.like_count || 0) + (media.comments_count || 0)
      }, 0)
    } catch {
      // Engagement-Berechnung optional
    }

    return {
      followers: account.followers_count,
      following: account.follows_count,
      mediaCount: account.media_count,
      recentEngagement,
    }
  }
}

export default InstagramClient
