import { describe, expect, it } from "vitest";
import {
  createSolvencyResponse,
  JsonRpcSolvencyClient,
  readSolvencyReport,
  type LiabilityReadPlan,
  type SolvencyDeployment,
  type SolvencyReadClient,
} from "../../api/v3/protocol-solvency";

const deployment: SolvencyDeployment = {
  chainId: 8453,
  address: "0x1111111111111111111111111111111111111111",
  name: "TestV3Contract",
  version: "v3",
  status: "active",
};
const observedAt = "2026-08-20T00:00:00.000Z";
const plan: LiabilityReadPlan = {
  id: "test-plan",
  supports: () => true,
  readLiabilities: async () => 9n,
};

describe("V3 solvency RPC failures", () => {
  it("returns HTTP 503 with null financial values when the RPC reports an error", async () => {
    const rpc = new JsonRpcSolvencyClient(
      { 8453: "https://rpc.example.test" },
      async () => Response.json({ jsonrpc: "2.0", id: 1, error: { code: -32000, message: "upstream unavailable" } }),
    );
    const dependencies = { deployments: [deployment], client: rpc, liabilityReadPlans: [plan], now: () => new Date(observedAt) };
    const report = await readSolvencyReport(dependencies);

    expect(report.status).toBe("degraded");
    expect(report.dataSourceErrors).toEqual([
      "8453:0x1111111111111111111111111111111111111111: block-read-failed: RPC -32000: upstream unavailable",
    ]);
    expect(report.rows[0]).toMatchObject({
      chainId: 8453,
      contractAddress: deployment.address,
      protocolVersion: "v3",
      contractStatus: "active",
      status: "degraded",
      blockNumber: null,
      blockHash: null,
      assetsWei: null,
      liabilitiesWei: null,
      deltaWei: null,
      dataSourceErrors: ["block-read-failed: RPC -32000: upstream unavailable"],
    });

    const response = await createSolvencyResponse(dependencies);
    expect(response.status).toBe(503);
    expect((await response.json()).rows[0].assetsWei).toBeNull();
  });

  it("does not manufacture zero assets or a delta after a balance read failure", async () => {
    const client: SolvencyReadClient = {
      getBlock: async () => ({ number: 123n, hash: `0x${"22".repeat(32)}` }),
      getBalance: async () => { throw new Error("balance transport timed out"); },
    };
    const report = await readSolvencyReport({
      deployments: [deployment],
      client,
      liabilityReadPlans: [plan],
      now: () => new Date(observedAt),
    });

    expect(report.status).toBe("degraded");
    expect(report.rows[0]).toMatchObject({
      blockNumber: "123",
      assetsWei: null,
      liabilitiesWei: "9",
      deltaWei: null,
      status: "degraded",
      dataSourceErrors: ["asset-balance-read-failed: balance transport timed out"],
    });
  });
});
