import crypto from 'node:crypto';
import { config } from './config.js';

const paypalBase = () => config.paypalEnv === 'live'
  ? 'https://api-m.paypal.com'
  : 'https://api-m.sandbox.paypal.com';

let tokenCache = { token: '', expiresAt: 0 };

export async function getAccessToken() {
  if (config.paypalEnv === 'mock') return 'mock-access-token';
  if (tokenCache.token && Date.now() < tokenCache.expiresAt - 60_000) return tokenCache.token;
  const auth = Buffer.from(`${config.paypalClientId}:${config.paypalClientSecret}`).toString('base64');
  const response = await fetch(`${paypalBase()}/v1/oauth2/token`, {
    method: 'POST',
    headers: {
      Authorization: `Basic ${auth}`,
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: 'grant_type=client_credentials',
    signal: AbortSignal.timeout(15_000)
  });
  if (!response.ok) throw new Error(`PayPal OAuth failed (${response.status})`);
  const data = await response.json();
  tokenCache = {
    token: data.access_token,
    expiresAt: Date.now() + (Number(data.expires_in || 300) * 1000)
  };
  return tokenCache.token;
}

export async function createPayPalOrder({ invoiceId }) {
  if (config.paypalEnv === 'mock') {
    return { id: `MOCK-${crypto.randomUUID()}`, status: 'CREATED' };
  }
  const accessToken = await getAccessToken();
  const response = await fetch(`${paypalBase()}/v2/checkout/orders`, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${accessToken}`,
      'Content-Type': 'application/json',
      'PayPal-Request-Id': invoiceId,
      Prefer: 'return=representation'
    },
    body: JSON.stringify({
      intent: 'CAPTURE',
      purchase_units: [{
        reference_id: config.product.sku,
        custom_id: config.product.sku,
        invoice_id: invoiceId,
        description: config.product.name,
        amount: {
          currency_code: config.product.currency,
          value: config.product.price,
          breakdown: {
            item_total: {
              currency_code: config.product.currency,
              value: config.product.price
            }
          }
        },
        items: [{
          name: config.product.name,
          description: 'Premium V1.0 digital PDF companion',
          sku: config.product.sku,
          quantity: '1',
          category: 'DIGITAL_GOODS',
          unit_amount: {
            currency_code: config.product.currency,
            value: config.product.price
          }
        }]
      }],
      payment_source: {
        paypal: {
          experience_context: {
            brand_name: 'Marloth Park Central',
            locale: 'en-US',
            shipping_preference: 'NO_SHIPPING',
            user_action: 'PAY_NOW',
            return_url: `${config.baseUrl}/success`,
            cancel_url: `${config.baseUrl}/?payment=cancelled`
          }
        }
      }
    }),
    signal: AbortSignal.timeout(20_000)
  });
  const data = await response.json();
  if (!response.ok) {
    const detail = data?.details?.[0]?.description || data?.message || 'PayPal create order failed';
    throw new Error(`${detail} (${response.status})`);
  }
  return data;
}

export async function capturePayPalOrder(orderId) {
  if (config.paypalEnv === 'mock') {
    return {
      id: orderId,
      status: 'COMPLETED',
      payer: { email_address: 'mock-buyer@example.com' },
      purchase_units: [{
        custom_id: config.product.sku,
        amount: { currency_code: config.product.currency, value: config.product.price },
        payments: {
          captures: [{
            id: `MOCK-CAPTURE-${crypto.randomUUID()}`,
            status: 'COMPLETED',
            amount: { currency_code: config.product.currency, value: config.product.price }
          }]
        }
      }]
    };
  }
  const accessToken = await getAccessToken();
  const response = await fetch(`${paypalBase()}/v2/checkout/orders/${encodeURIComponent(orderId)}/capture`, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${accessToken}`,
      'Content-Type': 'application/json',
      'PayPal-Request-Id': `capture-${orderId}`,
      Prefer: 'return=representation'
    },
    body: '{}',
    signal: AbortSignal.timeout(25_000)
  });
  const data = await response.json();
  if (!response.ok) {
    const issue = data?.details?.[0]?.issue;
    if (issue === 'ORDER_ALREADY_CAPTURED') return { alreadyCaptured: true, id: orderId };
    const detail = data?.details?.[0]?.description || data?.message || 'PayPal capture failed';
    throw new Error(`${detail} (${response.status})`);
  }
  return data;
}

export async function getPayPalOrder(orderId) {
  if (config.paypalEnv === 'mock') return null;
  const accessToken = await getAccessToken();
  const response = await fetch(`${paypalBase()}/v2/checkout/orders/${encodeURIComponent(orderId)}`, {
    headers: { Authorization: `Bearer ${accessToken}` },
    signal: AbortSignal.timeout(15_000)
  });
  if (!response.ok) throw new Error(`PayPal order lookup failed (${response.status})`);
  return response.json();
}

export function verifyCapturedProduct(orderData) {
  const purchaseUnit = orderData?.purchase_units?.[0];
  const capture = purchaseUnit?.payments?.captures?.[0];
  const amount = capture?.amount || purchaseUnit?.amount;
  const status = capture?.status || orderData?.status;
  const captureId = capture?.id;
  if (status !== 'COMPLETED') throw new Error('Payment is not completed.');
  if (!captureId) throw new Error('PayPal capture ID is missing.');
  if (amount?.currency_code !== config.product.currency || amount?.value !== config.product.price) {
    throw new Error('Captured amount or currency does not match the product.');
  }
  if (purchaseUnit?.custom_id && purchaseUnit.custom_id !== config.product.sku) {
    throw new Error('Captured product identifier does not match.');
  }
  return {
    captureId,
    payerEmail: orderData?.payer?.email_address || '',
    amount: amount.value,
    currency: amount.currency_code
  };
}

export async function verifyWebhookSignature(headers, webhookEvent) {
  if (config.paypalEnv === 'mock') return true;
  if (!config.paypalWebhookId) throw new Error('PAYPAL_WEBHOOK_ID is not configured.');
  const accessToken = await getAccessToken();
  const response = await fetch(`${paypalBase()}/v1/notifications/verify-webhook-signature`, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${accessToken}`,
      'Content-Type': 'application/json'
    },
    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: config.paypalWebhookId,
      webhook_event: webhookEvent
    }),
    signal: AbortSignal.timeout(20_000)
  });
  if (!response.ok) return false;
  const data = await response.json();
  return data.verification_status === 'SUCCESS';
}
