import crypto from 'crypto';

/**
 * NexaPay payment processor wrapper.
 *
 * NexaPay accepts cards (Visa/Mastercard/Apple Pay/Google Pay) on the customer
 * side and settles to VYNDR in stablecoin (USDC/USDT). The customer never
 * sees crypto.
 *
 * Required env vars (set on the deployment, never commit):
 *   NEXAPAY_API_KEY        — bearer token used for outbound API calls
 *   NEXAPAY_WEBHOOK_SECRET — HMAC secret for verifying inbound webhooks
 *   NEXAPAY_API_URL        — defaults to https://api.nexapay.one/v1
 *   NEXT_PUBLIC_SITE_URL   — used to construct redirect + webhook URLs
 */

const API_URL = process.env.NEXAPAY_API_URL || 'https://api.nexapay.one/v1';
const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3000';

export type NexaPayTier = 'analyst' | 'desk';

export interface CreatePaymentLinkParams {
  userId: string;
  tier: NexaPayTier;
  amount: number;       // dollars, e.g. 14.99
  description: string;
  founderPricing?: boolean;
}

export interface NexaPayPaymentLink {
  id: string;
  url: string;
  expires_at: string;
}

export interface NexaPayWebhookEvent {
  id: string;
  type: 'payment.succeeded' | 'payment.failed' | 'payment.refunded' | 'subscription.canceled';
  created: number;
  data: {
    payment_id: string;
    customer_id?: string;
    amount: number;
    currency: string;
    metadata: Record<string, string>;
    settled_amount?: number;
    settled_currency?: string;
  };
}

function requireApiKey(): string {
  const key = process.env.NEXAPAY_API_KEY;
  if (!key) {
    throw new Error('NEXAPAY_API_KEY is not set');
  }
  return key;
}

export async function createPaymentLink(params: CreatePaymentLinkParams): Promise<NexaPayPaymentLink> {
  const apiKey = requireApiKey();

  const body = {
    amount: Math.round(params.amount * 100),
    currency: 'USD',
    description: params.description,
    redirect_url: `${SITE_URL}/scan?upgraded=true`,
    cancel_url: `${SITE_URL}/?canceled=true#pricing`,
    webhook_url: `${SITE_URL}/api/webhook/nexapay`,
    customer_reference: params.userId,
    metadata: {
      userId: params.userId,
      tier: params.tier,
      type: 'subscription',
      founderPricing: String(params.founderPricing ?? false),
    },
  };

  const res = await fetch(`${API_URL}/payment-links`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(body),
  });

  if (!res.ok) {
    const errBody = await res.text().catch(() => '');
    throw new Error(`NexaPay create payment link failed (${res.status}): ${errBody}`);
  }

  return (await res.json()) as NexaPayPaymentLink;
}

export async function getTransaction(paymentId: string) {
  const apiKey = requireApiKey();
  const res = await fetch(`${API_URL}/payments/${paymentId}`, {
    headers: { Authorization: `Bearer ${apiKey}` },
  });
  if (!res.ok) {
    throw new Error(`NexaPay get transaction failed (${res.status})`);
  }
  return res.json();
}

/**
 * Verify a NexaPay webhook signature.
 * NexaPay sends `x-nexapay-signature: t=<unix>, v1=<hex>` where v1 is
 * HMAC-SHA256(secret, `${t}.${rawBody}`).
 */
export function verifyWebhookSignature(rawBody: string, signatureHeader: string | null): boolean {
  const secret = process.env.NEXAPAY_WEBHOOK_SECRET;
  if (!secret || !signatureHeader) return false;

  const parts = signatureHeader.split(',').reduce<Record<string, string>>((acc, part) => {
    const [k, v] = part.trim().split('=');
    if (k && v) acc[k] = v;
    return acc;
  }, {});

  const timestamp = parts['t'];
  const expected = parts['v1'];
  if (!timestamp || !expected) return false;

  // 5-minute replay window
  const ageSeconds = Math.abs(Date.now() / 1000 - Number(timestamp));
  if (!Number.isFinite(ageSeconds) || ageSeconds > 300) return false;

  const computed = crypto
    .createHmac('sha256', secret)
    .update(`${timestamp}.${rawBody}`)
    .digest('hex');

  try {
    return crypto.timingSafeEqual(Buffer.from(computed, 'hex'), Buffer.from(expected, 'hex'));
  } catch {
    return false;
  }
}

export const TIER_PRICING: Record<NexaPayTier, { regular: number; founder: number; label: string }> = {
  analyst: { regular: 24.99, founder: 14.99, label: 'VYNDR Analyst — Monthly' },
  desk:    { regular: 49.99, founder: 44.99, label: 'VYNDR Desk — Monthly' },
};
