// Payment provider abstraction (multi-tenant).
// Tiap guild punya key sendiri (dari payment_configs, terenkripsi). Fungsi di sini
// menerima `config` (key sudah didekripsi) — fallback ke ENV untuk kompatibilitas lama.
//
// Signature per spec resmi:
//   Tripay   -> HMAC-SHA256
//   Midtrans -> SHA-512 (order_id + status_code + gross_amount + server_key)

import crypto from 'crypto';

// ---- Buat invoice (dipanggil saat checkout) ----
export async function createInvoice({ invoiceId, amount, productName, buyerEmail, buyerName, config }) {
  // config: { provider, tripayApiKey, tripayPrivateKey, tripayMerchantCode, ... }
  const provider = (config?.provider || process.env.PAYMENT_PROVIDER || 'mock').toLowerCase();

  if (provider === 'tripay') {
    return createTripayInvoice({ invoiceId, amount, productName, buyerEmail, buyerName, config });
  }
  if (provider === 'pakasir') {
    return createPakasirInvoice({ invoiceId, amount, config });
  }
  // Default: mock — auto-success page (HANYA dev)
  const base = process.env.WEB_BASE_URL || 'http://localhost:4002';
  return { provider: 'mock', url: `${base}/mock-pay?invoice=${invoiceId}&amount=${amount}` };
}

async function createTripayInvoice({ invoiceId, amount, productName, buyerEmail, buyerName, config }) {
  const apiKey = config?.tripayApiKey || process.env.TRIPAY_API_KEY;
  const privateKey = config?.tripayPrivateKey || process.env.TRIPAY_PRIVATE_KEY;
  const merchantCode = config?.tripayMerchantCode || process.env.TRIPAY_MERCHANT_CODE;
  if (!apiKey || !privateKey || !merchantCode) throw new Error('Tripay keys belum lengkap');

  const signature = crypto
    .createHmac('sha256', privateKey)
    .update(merchantCode + invoiceId + amount)
    .digest('hex');

  const body = {
    method: 'QRIS',
    merchant_ref: invoiceId,
    amount,
    customer_name: buyerName,
    customer_email: buyerEmail,
    order_items: [{ name: productName, price: amount, quantity: 1 }],
    callback_url: `${process.env.WEB_BASE_URL}/webhook/tripay`,
    return_url: `${process.env.WEB_BASE_URL}/order/${invoiceId}`,
    expired_time: Math.floor(Date.now() / 1000) + 3600,
    signature,
  };

  const r = await fetch('https://tripay.co.id/api/transaction/create', {
    method: 'POST',
    headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  });
  const data = await r.json();
  if (!data.success) throw new Error(data.message || 'Tripay create failed');
  return { provider: 'tripay', url: data.data.checkout_url, ref: data.data.reference };
}

// ---- Verifikasi signature webhook (per-key, multi-tenant) ----

// Tripay: HMAC-SHA256 dari rawBody pakai private key merchant. Constant-time compare.
export function verifyTripaySignature(rawBody, signature, privateKey) {
  if (!privateKey || !signature) return false;
  const computed = crypto.createHmac('sha256', privateKey).update(rawBody).digest('hex');
  return safeEqualHex(computed, signature);
}

// Midtrans: SHA-512( order_id + status_code + gross_amount + server_key ). Per spec resmi.
export function verifyMidtransSignature(body, serverKey) {
  if (!serverKey || !body?.signature_key) return false;
  const raw = `${body.order_id}${body.status_code}${body.gross_amount}${serverKey}`;
  const computed = crypto.createHash('sha512').update(raw).digest('hex');
  return safeEqualHex(computed, body.signature_key);
}

// Bandingkan dua hex string secara constant-time (anti timing attack)
function safeEqualHex(a, b) {
  try {
    const ba = Buffer.from(String(a), 'hex');
    const bb = Buffer.from(String(b), 'hex');
    return ba.length === bb.length && crypto.timingSafeEqual(ba, bb);
  } catch {
    return false;
  }
}

// ---- Pakasir: POST transactioncreate/qris, return checkout URL ----
async function createPakasirInvoice({ invoiceId, amount, config }) {
  const slug = config?.pakasirSlug || process.env.PAKASIR_SLUG;
  const apiKey = config?.pakasirApiKey || process.env.PAKASIR_API_KEY;
  if (!slug || !apiKey) throw new Error('Pakasir credentials belum lengkap (slug + API key)');

  const r = await fetch('https://app.pakasir.com/api/transactioncreate/qris', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ project: slug, order_id: invoiceId, amount: String(amount), api_key: apiKey }),
  });
  const data = await r.json();
  if (!data.payment) {
    const directUrl = `https://app.pakasir.com/pay/${slug}/${amount}?order_id=${invoiceId}&redirect=${encodeURIComponent(process.env.WEB_BASE_URL + '/order/' + invoiceId)}`;
    return { provider: 'pakasir', url: directUrl };
  }
  return { provider: 'pakasir', url: `https://app.pakasir.com/pay/${slug}/${amount}?order_id=${invoiceId}&redirect=${encodeURIComponent(process.env.WEB_BASE_URL + '/order/' + invoiceId)}`, ref: data.payment.payment_number };
}

// Pakasir callback verification: call transactiondetail to confirm status
export async function verifyPakasirCallback(orderId, amount, apiKey, slug) {
  const params = new URLSearchParams({ order_id: orderId, api_key: apiKey, project: slug });
  const r = await fetch(`https://app.pakasir.com/api/transactiondetail?${params}`);
  const data = await r.json();
  if (!data.payment) return { paid: false };
  return {
    paid: data.payment.status === 'success' || data.payment.status === 'paid',
    amount: data.payment.total_payment,
    orderId: data.payment.order_id,
  };
}

// ---- Backward-compat (single-tenant via env) — masih dipakai kalau config kosong ----
export function verifyTripayCallback(rawBody, signature) {
  return verifyTripaySignature(rawBody, signature, process.env.TRIPAY_PRIVATE_KEY);
}
