/**
 * درگاه زرین‌پال (API نسخه ۴) — https://www.zarinpal.com/docs/paymentGateway/
 * در حالت sandbox هر merchant_id با قالب UUID پذیرفته می‌شود و پولی جابه‌جا نمی‌شود.
 */
import type { PaymentGateway } from "./gateway";

export function zarinpalGateway(merchantId: string, sandbox: boolean): PaymentGateway {
  const host = sandbox ? "https://sandbox.zarinpal.com" : "https://payment.zarinpal.com";

  async function post<T>(path: string, body: Record<string, unknown>): Promise<T> {
    const res = await fetch(`${host}/pg/v4/payment/${path}`, {
      method: "POST",
      headers: { "Content-Type": "application/json", Accept: "application/json" },
      body: JSON.stringify({ merchant_id: merchantId, ...body }),
      signal: AbortSignal.timeout(15_000),
    });
    return (await res.json()) as T;
  }

  type Resp<D> = { data: D | []; errors: { code?: number; message?: string } | [] };

  return {
    id: "zarinpal",
    async request({ amountRial, description, callbackUrl, mobile, orderCode }) {
      const r = await post<Resp<{ code: number; authority: string }>>("request.json", {
        amount: amountRial,
        currency: "IRR",
        description,
        callback_url: callbackUrl,
        metadata: { mobile, order_id: orderCode },
      });
      const data = Array.isArray(r.data) ? undefined : r.data;
      if (data?.code !== 100) throw new Error(`زرین‌پال: ${Array.isArray(r.errors) ? "خطای ناشناخته" : r.errors.message}`);
      return { authority: data.authority, redirectUrl: `${host}/pg/StartPay/${data.authority}` };
    },
    parseCallback(params) {
      return { authority: params.get("Authority"), ok: params.get("Status") === "OK" };
    },
    async verify({ authority, amountRial }) {
      const r = await post<Resp<{ code: number; ref_id: number; card_pan?: string }>>("verify.json", { amount: amountRial, authority });
      const data = Array.isArray(r.data) ? undefined : r.data;
      // ۱۰۰: موفق، ۱۰۱: قبلاً تأیید شده
      if (data && (data.code === 100 || data.code === 101)) return { ok: true, refId: String(data.ref_id), cardPan: data.card_pan };
      return { ok: false, message: Array.isArray(r.errors) ? "تراکنش تأیید نشد" : (r.errors.message ?? "تراکنش تأیید نشد") };
    },
  };
}
