/**
 * PayPal server-side client
 * Handles OAuth2 authentication and Orders API v2
 */

import { logger } from "@/lib/logger"

const PAYPAL_API_URL = process.env.PAYPAL_API_URL || "https://api-m.sandbox.paypal.com"
const PAYPAL_CLIENT_ID = process.env.PAYPAL_CLIENT_ID || ""
const PAYPAL_CLIENT_SECRET = process.env.PAYPAL_CLIENT_SECRET || ""

interface CachedToken {
  token: string
  expiresAt: number
}

let cachedToken: CachedToken | null = null

export interface PayPalOrderResult {
  id: string
  status: string
}

export interface PayPalCaptureResult {
  id: string
  status: string
  payer?: {
    email_address?: string
  }
  purchase_units: Array<{
    reference_id?: string
    payments: {
      captures: Array<{
        id: string
        status: string
        amount: {
          currency_code: string
          value: string
        }
      }>
    }
  }>
}

export class PayPalClient {
  /**
   * Get OAuth2 access token using client_credentials grant.
   * Caches the token until 60 seconds before expiry.
   */
  static async getAccessToken(): Promise<string> {
    if (cachedToken && Date.now() < cachedToken.expiresAt) {
      return cachedToken.token
    }

    const credentials = Buffer.from(`${PAYPAL_CLIENT_ID}:${PAYPAL_CLIENT_SECRET}`).toString("base64")

    const response = await fetch(`${PAYPAL_API_URL}/v1/oauth2/token`, {
      method: "POST",
      headers: {
        "Authorization": `Basic ${credentials}`,
        "Content-Type": "application/x-www-form-urlencoded",
      },
      body: "grant_type=client_credentials",
    })

    if (!response.ok) {
      const errorText = await response.text()
      logger.error("v0", "PayPal OAuth token request failed", {
        status: response.status,
        error: errorText,
      })
      throw new Error(`PayPal OAuth failed: ${response.status}`)
    }

    const data = await response.json()
    cachedToken = {
      token: data.access_token,
      expiresAt: Date.now() + (data.expires_in - 60) * 1000,
    }

    return data.access_token
  }

  /**
   * Create a PayPal order (equivalent to Stripe's createPaymentIntent)
   */
  static async createOrder(params: {
    orderId: number
    amountCents: number
    currency: string
    description?: string
  }): Promise<PayPalOrderResult> {
    const { orderId, amountCents, currency, description } = params
    const token = await this.getAccessToken()

    const amountStr = (amountCents / 100).toFixed(2)

    const response = await fetch(`${PAYPAL_API_URL}/v2/checkout/orders`, {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${token}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        intent: "CAPTURE",
        purchase_units: [
          {
            reference_id: `wc_order_${orderId}`,
            description: description || `Order #${orderId}`,
            amount: {
              currency_code: currency.toUpperCase(),
              value: amountStr,
            },
          },
        ],
      }),
    })

    if (!response.ok) {
      const errorText = await response.text()
      logger.error("v0", "PayPal create order failed", {
        status: response.status,
        error: errorText,
        orderId,
      })
      throw new Error(`PayPal create order failed: ${response.status}`)
    }

    const data = await response.json()

    logger.info("v0", "PayPal order created", {
      paypalOrderId: data.id,
      status: data.status,
      wcOrderId: orderId,
      amount: amountStr,
    })

    return { id: data.id, status: data.status }
  }

  /**
   * Capture an approved PayPal order (collects payment synchronously)
   */
  static async captureOrder(paypalOrderId: string): Promise<PayPalCaptureResult> {
    const token = await this.getAccessToken()

    const response = await fetch(`${PAYPAL_API_URL}/v2/checkout/orders/${paypalOrderId}/capture`, {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${token}`,
        "Content-Type": "application/json",
      },
    })

    if (!response.ok) {
      const errorText = await response.text()
      logger.error("v0", "PayPal capture failed", {
        status: response.status,
        error: errorText,
        paypalOrderId,
      })
      throw new Error(`PayPal capture failed: ${response.status}`)
    }

    const data: PayPalCaptureResult = await response.json()

    logger.info("v0", "PayPal order captured", {
      paypalOrderId: data.id,
      status: data.status,
      captureId: data.purchase_units?.[0]?.payments?.captures?.[0]?.id,
    })

    return data
  }

  /**
   * Get PayPal order details (for reuse/validation)
   */
  static async getOrder(paypalOrderId: string): Promise<PayPalOrderResult> {
    const token = await this.getAccessToken()

    const response = await fetch(`${PAYPAL_API_URL}/v2/checkout/orders/${paypalOrderId}`, {
      method: "GET",
      headers: {
        "Authorization": `Bearer ${token}`,
        "Content-Type": "application/json",
      },
    })

    if (!response.ok) {
      throw new Error(`PayPal get order failed: ${response.status}`)
    }

    return response.json()
  }
}
