const { expect } = require("chai");
const { ethers } = require("hardhat");

describe("AereValidatorManifest", () => {
  let val1, val2, ds;
  const DIGEST_A = ethers.keccak256(ethers.toUtf8Bytes("aere-besu-reproducible-A"));
  const DIGEST_B = ethers.keccak256(ethers.toUtf8Bytes("aere-besu-reproducible-B"));

  beforeEach(async () => {
    [val1, val2] = await ethers.getSigners();
    const F = await ethers.getContractFactory("AereValidatorManifest");
    ds = await F.deploy();
    await ds.waitForDeployment();
  });

  it("a validator declares + we read back", async () => {
    await expect(
      ds.connect(val1).declare(
        DIGEST_A,
        "https://aere.network/.well-known/besu-image-digest",
        "AERE Foundation",
        "EU-Central / DE / example-dc-1"
      )
    ).to.emit(ds, "CommitmentDeclared");
    const c = await ds.commitmentOf(val1.address);
    expect(c.binaryDigest).to.equal(DIGEST_A);
    expect(c.operatorLabel).to.equal("AERE Foundation");
    expect(c.serial).to.equal(1n);
    expect(await ds.isDeclared(val1.address)).to.equal(true);
  });

  it("rejects malformed declarations", async () => {
    await expect(
      ds.connect(val1).declare(ethers.ZeroHash, "u", "l", "r")
    ).to.be.revertedWithCustomError(ds, "ZeroDigest");
    await expect(
      ds.connect(val1).declare(DIGEST_A, "", "l", "r")
    ).to.be.revertedWithCustomError(ds, "EmptyManifestUri");
    await expect(
      ds.connect(val1).declare(DIGEST_A, "u", "", "r")
    ).to.be.revertedWithCustomError(ds, "EmptyOperatorLabel");
  });

  it("overwriting bumps serial; serials are per-validator", async () => {
    await ds.connect(val1).declare(DIGEST_A, "u", "l", "r");
    await ds.connect(val1).declare(DIGEST_B, "u", "l", "r");
    expect((await ds.commitmentOf(val1.address)).serial).to.equal(2n);
    expect((await ds.commitmentOf(val1.address)).binaryDigest).to.equal(DIGEST_B);

    await ds.connect(val2).declare(DIGEST_A, "u", "l", "r");
    expect((await ds.commitmentOf(val2.address)).serial).to.equal(1n);
  });

  it("validators write only their own slot", async () => {
    await ds.connect(val1).declare(DIGEST_A, "u", "l", "r");
    expect(await ds.isDeclared(val2.address)).to.equal(false);
  });
});
