import { google } from 'googleapis'
import { OAuth2Client } from 'google-auth-library'

export interface ProductData {
  offerId: string
  title: string
  description: string
  link: string
  imageLink: string
  price: {
    value: string
    currency: string
  }
  availability: 'in stock' | 'out of stock' | 'preorder'
  brand?: string
  gtin?: string
  mpn?: string
  condition?: 'new' | 'refurbished' | 'used'
  category?: string
}

export class GoogleMerchantService {
  private oauth2Client: OAuth2Client
  private merchantId: string

  constructor() {
    const clientId = process.env.GOOGLE_MERCHANT_CLIENT_ID
    const clientSecret = process.env.GOOGLE_MERCHANT_CLIENT_SECRET
    const redirectUri = process.env.GOOGLE_MERCHANT_REDIRECT_URI || 'http://localhost:3000/api/merchant/callback'

    if (!clientId || !clientSecret) {
      throw new Error('Google Merchant credentials not configured. Please set GOOGLE_MERCHANT_CLIENT_ID and GOOGLE_MERCHANT_CLIENT_SECRET in .env')
    }

    this.oauth2Client = new google.auth.OAuth2(
      clientId,
      clientSecret,
      redirectUri
    )
    this.merchantId = process.env.GOOGLE_MERCHANT_ACCOUNT_ID || ''
  }

  /**
   * Gera URL de autenticação OAuth
   */
  getAuthUrl(): string {
    return this.oauth2Client.generateAuthUrl({
      access_type: 'offline',
      scope: [
        'https://www.googleapis.com/auth/content',
      ],
      prompt: 'consent', // Força a obtenção do refresh token
    })
  }

  /**
   * Troca o código de autorização por tokens
   */
  async getTokens(code: string): Promise<{ access_token?: string | null; refresh_token?: string | null }> {
    const { tokens } = await this.oauth2Client.getToken(code)
    return tokens
  }

  /**
   * Configura as credenciais usando refresh token
   */
  async authenticate(): Promise<OAuth2Client> {
    const refreshToken = process.env.GOOGLE_MERCHANT_REFRESH_TOKEN
    if (!refreshToken) {
      throw new Error('GOOGLE_MERCHANT_REFRESH_TOKEN not configured. Please authenticate first.')
    }

    this.oauth2Client.setCredentials({
      refresh_token: refreshToken,
    })

    // Verifica se precisa renovar o access token
    try {
      await this.oauth2Client.getAccessToken()
    } catch (error) {
      throw new Error('Failed to authenticate. Please re-authenticate to get a new refresh token.')
    }

    return this.oauth2Client
  }

  /**
   * Insere um produto no Google Merchant Center
   */
  async insertProduct(product: ProductData) {
    if (!this.merchantId) {
      throw new Error('GOOGLE_MERCHANT_ACCOUNT_ID not configured')
    }

    const auth = await this.authenticate()

    try {
      // Usando Content API (mais estável que Merchant API para alguns casos)
      const content = google.content({
        version: 'v2.1',
        auth,
      })

      const response = await content.products.insert({
        merchantId: this.merchantId,
        requestBody: {
          offerId: product.offerId,
          title: product.title,
          description: product.description,
          link: product.link,
          imageLink: product.imageLink,
          contentLanguage: 'pt',
          targetCountry: 'PT',
          channel: 'online',
          price: {
            value: product.price.value,
            currency: product.price.currency,
          },
          availability: product.availability,
          brand: product.brand,
          gtin: product.gtin,
          mpn: product.mpn,
          condition: product.condition || 'new',
          googleProductCategory: product.category || '',
        },
      })

      return response.data
    } catch (error: any) {
      const errorData = error.response?.data || {}
      const errorMessage = errorData.error?.message || error.message || 'Unknown error'
      const errorCode = errorData.error?.code || error.code
      
      console.error('Error inserting product:', {
        product: product.title,
        offerId: product.offerId,
        error: errorMessage,
        code: errorCode,
        fullError: errorData,
      })
      
      // Preservar o erro original para melhor debugging
      const enhancedError = new Error(`Failed to insert product ${product.title}: ${errorMessage}`)
      ;(enhancedError as any).originalError = error
      ;(enhancedError as any).errorData = errorData
      ;(enhancedError as any).errorCode = errorCode
      throw enhancedError
    }
  }

  /**
   * Atualiza um produto existente
   */
  async updateProduct(offerId: string, product: Partial<ProductData>) {
    if (!this.merchantId) {
      throw new Error('GOOGLE_MERCHANT_ACCOUNT_ID not configured')
    }

    const auth = await this.authenticate()

    try {
      const content = google.content({
        version: 'v2.1',
        auth,
      })

      const response = await content.products.update({
        merchantId: this.merchantId,
        productId: `online:pt:${offerId}`,
        requestBody: {
          offerId,
          title: product.title,
          description: product.description,
          link: product.link,
          imageLink: product.imageLink,
          contentLanguage: 'pt',
          targetCountry: 'PT',
          channel: 'online',
          price: product.price ? {
            value: product.price.value,
            currency: product.price.currency,
          } : undefined,
          availability: product.availability,
          brand: product.brand,
          condition: product.condition || 'new',
        },
      })

      return response.data
    } catch (error: any) {
      console.error('Error updating product:', error.response?.data || error.message)
      throw new Error(`Failed to update product: ${error.response?.data?.error?.message || error.message}`)
    }
  }

  /**
   * Lista produtos do Merchant Center
   */
  async listProducts(maxResults: number = 50) {
    if (!this.merchantId) {
      throw new Error('GOOGLE_MERCHANT_ACCOUNT_ID not configured')
    }

    const auth = await this.authenticate()

    try {
      const content = google.content({
        version: 'v2.1',
        auth,
      })

      const response = await content.products.list({
        merchantId: this.merchantId,
        maxResults,
      })

      return response.data
    } catch (error: any) {
      console.error('Error listing products:', error.response?.data || error.message)
      throw new Error(`Failed to list products: ${error.response?.data?.error?.message || error.message}`)
    }
  }

  /**
   * Deleta um produto
   */
  async deleteProduct(offerId: string) {
    if (!this.merchantId) {
      throw new Error('GOOGLE_MERCHANT_ACCOUNT_ID not configured')
    }

    const auth = await this.authenticate()

    try {
      const content = google.content({
        version: 'v2.1',
        auth,
      })

      await content.products.delete({
        merchantId: this.merchantId,
        productId: `online:pt:${offerId}`,
      })

      return { success: true }
    } catch (error: any) {
      console.error('Error deleting product:', error.response?.data || error.message)
      throw new Error(`Failed to delete product: ${error.response?.data?.error?.message || error.message}`)
    }
  }
}
