import { createHmac, timingSafeEqual } from "node:crypto";
import { nanoid } from "nanoid";

const PAYSTACK_API_URL = "https://api.paystack.co";

export type PaystackTransactionStatus = "success" | "failed" | "abandoned" | "pending";

export type PaystackTransaction = {
  reference: string;
  status: PaystackTransactionStatus;
  amount: number;
  currency: string;
  metadata?: Record<string, unknown> | string | null;
  customer?: { email?: string | null } | null;
};

type PaystackResponse<T> = { status: boolean; message: string; data: T };

function getPaystackSecret() {
  const secret = process.env.PAYSTACK_SECRET_KEY;
  if (!secret) throw new Error("Paystack is not configured");
  return secret;
}

async function paystackRequest<T>(path: string, init: RequestInit): Promise<T> {
  const response = await fetch(`${PAYSTACK_API_URL}${path}`, {
    ...init,
    headers: {
      Authorization: `Bearer ${getPaystackSecret()}`,
      "Content-Type": "application/json",
      ...(init.headers ?? {}),
    },
  });
  const body = await response.json().catch(() => null) as PaystackResponse<T> | null;
  if (!response.ok || !body?.status) {
    throw new Error(body?.message || `Paystack request failed with HTTP ${response.status}`);
  }
  return body.data;
}

export function makePaystackReference(orderId: number) {
  return `gngpasse_${orderId}_${nanoid(12)}`;
}

export async function initializePaystackTransaction(input: {
  email: string;
  amountMinor: number;
  currency: string;
  reference: string;
  callbackUrl: string;
  metadata: Record<string, unknown>;
}) {
  if (input.amountMinor <= 0) throw new Error("Paystack transactions must have a positive amount");
  return paystackRequest<{ authorization_url: string; access_code: string; reference: string }>("/transaction/initialize", {
    method: "POST",
    body: JSON.stringify({
      email: input.email,
      amount: input.amountMinor,
      currency: input.currency,
      reference: input.reference,
      callback_url: input.callbackUrl,
      metadata: input.metadata,
    }),
  });
}

export function verifyPaystackWebhookSignature(rawBody: Buffer | string, signature: string | undefined, secret = process.env.PAYSTACK_SECRET_KEY) {
  if (!signature || !secret) return false;
  const expected = createHmac("sha512", secret).update(rawBody).digest("hex");
  const received = Buffer.from(signature, "utf8");
  const computed = Buffer.from(expected, "utf8");
  return received.length === computed.length && timingSafeEqual(received, computed);
}

export function isSuccessfulPaystackPayment(input: { status: string; amount: number; currency: string }, expected: { amountMinor: number; currency: string }) {
  return input.status === "success" && input.amount === expected.amountMinor && input.currency.toUpperCase() === expected.currency.toUpperCase();
}

export async function verifyPaystackTransaction(reference: string) {
  return paystackRequest<PaystackTransaction>(`/transaction/verify/${encodeURIComponent(reference)}`, { method: "GET" });
}
