const BASE_URL = process.env.PAYPAL_BASE_URL ?? 'https://api-m.paypal.com'
const CLIENT_ID = process.env.PAYPAL_CLIENT_ID ?? ''
const CLIENT_SECRET = process.env.PAYPAL_CLIENT_SECRET ?? ''

let cachedToken: { token: string; expiresAt: number } | null = null

async function getAccessToken(): Promise<string> {
  if (cachedToken && Date.now() < cachedToken.expiresAt - 30_000) {
    return cachedToken.token
  }

  const res = await fetch(`${BASE_URL}/v1/oauth2/token`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      Authorization: `Basic ${Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString('base64')}`,
    },
    body: 'grant_type=client_credentials',
  })

  if (!res.ok) throw new Error('PayPal: failed to obtain access token')
  const json = await res.json() as Record<string, unknown>
  cachedToken = { token: json.access_token as string, expiresAt: Date.now() + (json.expires_in as number) * 1000 }
  return cachedToken.token
}

async function ppFetch(path: string, init?: RequestInit) {
  const token = await getAccessToken()
  const res = await fetch(`${BASE_URL}${path}`, {
    ...init,
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${token}`,
      ...(init?.headers as Record<string, string> ?? {}),
    },
  })
  if (!res.ok) {
    const err = await res.json().catch(() => ({})) as Record<string, unknown>
    throw new Error(`PayPal ${path} failed: ${(err?.message as string) ?? res.statusText}`)
  }
  return res.json() as Promise<Record<string, unknown>>
}

export interface PayPalCreateOrderParams {
  amount: number
  currency: string
  orderId: string
  description: string
  returnUrl: string
  cancelUrl: string
}

export interface PayPalOrderResult {
  orderId: string
  approveUrl: string
  status: string
}

export async function createOrder(params: PayPalCreateOrderParams): Promise<PayPalOrderResult> {
  const json = await ppFetch('/v2/checkout/orders', {
    method: 'POST',
    body: JSON.stringify({
      intent: 'CAPTURE',
      purchase_units: [
        {
          reference_id: params.orderId,
          description: params.description,
          amount: {
            currency_code: params.currency,
            value: (params.amount / 100).toFixed(2),
          },
        },
      ],
      application_context: {
        return_url: params.returnUrl,
        cancel_url: params.cancelUrl,
        brand_name: 'RentalDriveGo',
        user_action: 'PAY_NOW',
      },
    }),
  })

  const approveLink = (json.links as Array<{ rel: string; href: string }> | undefined)?.find((l) => l.rel === 'approve')
  return {
    orderId: json.id as string,
    approveUrl: approveLink?.href ?? '',
    status: json.status as string,
  }
}

export async function captureOrder(paypalOrderId: string) {
  return ppFetch(`/v2/checkout/orders/${paypalOrderId}/capture`, { method: 'POST', body: '{}' })
}

export async function refundCapture(captureId: string, amount: number, currency: string, note?: string) {
  return ppFetch(`/v2/payments/captures/${captureId}/refund`, {
    method: 'POST',
    body: JSON.stringify({
      amount: { currency_code: currency, value: (amount / 100).toFixed(2) },
      note_to_payer: note,
    }),
  })
}

export async function verifyWebhookEvent(headers: Record<string, string | undefined>, rawBody: string) {
  try {
    const json = await ppFetch('/v1/notifications/verify-webhook-signature', {
      method: 'POST',
      body: JSON.stringify({
        auth_algo: headers['paypal-auth-algo'],
        cert_url: headers['paypal-cert-url'],
        transmission_id: headers['paypal-transmission-id'],
        transmission_sig: headers['paypal-transmission-sig'],
        transmission_time: headers['paypal-transmission-time'],
        webhook_id: process.env.PAYPAL_WEBHOOK_ID ?? '',
        webhook_event: JSON.parse(rawBody),
      }),
    })
    return (json as Record<string, unknown>).verification_status === 'SUCCESS'
  } catch {
    return false
  }
}

export function isConfigured(): boolean {
  return !!(CLIENT_ID && CLIENT_SECRET && CLIENT_ID !== 'your-paypal-client-id')
}
