import { describe, expect, it } from "vitest";

import {
  AmountPrecisionError,
  AttestationNotReadyError,
  IrisRequestError,
  SubmissionTimeoutError,
  TransferError,
  type TransferErrorCode,
} from "../src/errors.js";

describe("SDK error taxonomy", () => {
  it("preserves TransferError fields and prototype chain", () => {
    const code: TransferErrorCode = "ATTESTATION_NOT_READY";
    const error = new TransferError("pending", "0xburn", "0xattestation", code);
    expect(error).toBeInstanceOf(Error);
    expect(error).toBeInstanceOf(TransferError);
    expect(error).toMatchObject({ name: "TransferError", message: "pending", burnTxHash: "0xburn", attestationHash: "0xattestation", code });
    expect(new TransferError("failed", "0xburn")).toMatchObject({ attestationHash: undefined, code: undefined });
  });

  it("preserves AttestationNotReadyError recovery data", () => {
    const error = new AttestationNotReadyError("not ready", "0xburn");
    expect(error).toBeInstanceOf(Error);
    expect(error).toBeInstanceOf(AttestationNotReadyError);
    expect(error).toMatchObject({ name: "AttestationNotReadyError", message: "not ready", burnTxHash: "0xburn" });
  });

  it("preserves IrisRequestError optional status", () => {
    const error = new IrisRequestError("unavailable", 503);
    expect(error).toBeInstanceOf(Error);
    expect(error).toBeInstanceOf(IrisRequestError);
    expect(error).toMatchObject({ name: "IrisRequestError", message: "unavailable", status: 503 });
    expect(new IrisRequestError("network failure").status).toBeUndefined();
  });

  it("preserves SubmissionTimeoutError hash", () => {
    const error = new SubmissionTimeoutError("timed out", "0xtx");
    expect(error).toBeInstanceOf(Error);
    expect(error).toBeInstanceOf(SubmissionTimeoutError);
    expect(error).toMatchObject({ name: "SubmissionTimeoutError", message: "timed out", hash: "0xtx" });
  });

  it("preserves AmountPrecisionError details", () => {
    const error = new AmountPrecisionError("1.2345678", 7, 6, "stellar");
    expect(error).toBeInstanceOf(Error);
    expect(error).toBeInstanceOf(AmountPrecisionError);
    expect(error).toMatchObject({ name: "AmountPrecisionError", amount: "1.2345678", precision: 7, supportedDecimals: 6, destination: "stellar" });
  });
});
