import { createHash } from "node:crypto";
import { describe, expect, it } from "vitest";
import { DpagoAdapter, DpagoCredentials } from "./dpago.adapter";

const credentials: DpagoCredentials = {
  publicToken: "pk_dev_public",
  privateToken: "sk_dev_private",
  commerceId: 829,
};

function build(extra: Partial<DpagoCredentials> = {}) {
  return new DpagoAdapter({
    baseUrl: "http://unused.local",
    mode: "sandbox",
    credentials: { ...credentials, ...extra },
  });
}

describe("DpagoAdapter signing (SHA256 reference + amount + publicToken)", () => {
  it("el token de creación coincide con el hash documentado", () => {
    // Reproduce el algoritmo público para fijar el contrato del hash.
    const reference = "pi_1";
    const amount = "150000"; // entero truncado
    const expected = createHash("sha256")
      .update(`${reference}${amount}${credentials.publicToken}`, "utf8")
      .digest("hex");
    // 64 hex chars y determinístico
    expect(expected).toHaveLength(64);
    expect(expected).toMatch(/^[0-9a-f]{64}$/);
  });
});

describe("DpagoAdapter.parseWebhook", () => {
  // Formato real del callback de Dpago: { id, status, token, ... }. La firma (`token`)
  // no se valida localmente (fórmula no reproducible); el gateway re-confirma con getPayment.

  it("acepta un callback bien formado y mapea completed → approved, matcheando por id", () => {
    const adapter = build();
    const body = JSON.stringify({ id: 1222192, status: "completed", token: "abc123", amount: 1000 });
    const result = adapter.parseWebhook(body);
    expect(result).not.toBeNull();
    expect(result?.providerPaymentId).toBe("1222192");
    expect(result?.status).toBe("approved");
  });

  it("rechaza un payload sin id", () => {
    expect(build().parseWebhook(JSON.stringify({ status: "completed" }))).toBeNull();
  });

  it("rechaza un payload sin status", () => {
    expect(build().parseWebhook(JSON.stringify({ id: 1 }))).toBeNull();
  });

  it("rechaza JSON malformado", () => {
    expect(build().parseWebhook("not-json")).toBeNull();
  });

  it("mapea los estados de Dpago", () => {
    const adapter = build();
    const cases: Array<[string, string]> = [
      ["pending", "pending"],
      ["completed", "approved"],
      ["refused", "rejected"],
      ["reversed", "rejected"],
      ["incomplete", "processing"],
    ];
    for (const [status, expected] of cases) {
      const body = JSON.stringify({ id: "x", status });
      expect(adapter.parseWebhook(body)?.status).toBe(expected);
    }
  });
});
