/**
 * Proves the generated constants can replace the website's hand-maintained V2
 * address map with zero behavioral change.
 *
 * The nested website source (`v2-repo/repos/theloopbreaker-site`) is a vendored
 * mirror and is git-ignored in this repository, so the test resolves it from
 * candidate paths and skips when it is not checked out locally.
 */
import { existsSync, readFileSync } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { describe, expect, it } from "vitest";
import { V2_ADDRESSES } from "../generated/website-addresses.generated";
import { allLegacyContracts, legacyContractsForChain } from "../src/v2-legacy-adapter";

const HERE = path.dirname(fileURLToPath(import.meta.url));
const REPO_ROOT = path.resolve(HERE, "../../..");
const REL_CONTRACTS = "app/lib/contracts.ts";

function resolveSiteRoot(): string | null {
  const candidates = [
    process.env.VAULTFIRE_V2_SITE_ROOT,
    path.join(REPO_ROOT, "v2-repo/repos/theloopbreaker-site"),
    path.resolve(REPO_ROOT, "../vaultfire-v3/v2-repo/repos/theloopbreaker-site"),
  ].filter((value): value is string => Boolean(value));
  for (const candidate of candidates) {
    if (existsSync(path.join(candidate, REL_CONTRACTS))) return candidate;
  }
  return null;
}

const siteRoot = resolveSiteRoot();

describe("legacy adapter shape", () => {
  it("reproduces the website Contract shape from generated constants", () => {
    const getABI = (name: string) => [{ type: "function", name }];
    const all = allLegacyContracts(getABI);
    expect(all).toHaveLength(V2_ADDRESSES.length);
    expect(Object.keys(all[0]).sort()).toEqual(["abi", "address", "chain", "name"]);
    expect(legacyContractsForChain("base", getABI).every((c) => c.chain === "base")).toBe(true);
  });
});

describe.skipIf(siteRoot === null)("parity with the nested website address map", () => {
  it("matches every hand-maintained (name, chain) -> address pair", () => {
    const source = readFileSync(path.join(siteRoot!, REL_CONTRACTS), "utf8");
    const pattern =
      /name:\s*"([^"]+)",\s*address:\s*"(0x[0-9a-fA-F]{40})",\s*chain:\s*"(base|avalanche|arbitrum|polygon)"/g;
    const siteEntries = [...source.matchAll(pattern)].map((m) => ({
      name: m[1],
      address: m[2],
      chain: m[3],
    }));

    expect(siteEntries.length).toBeGreaterThan(0);
    expect(siteEntries).toHaveLength(V2_ADDRESSES.length);

    const generated = new Map(
      V2_ADDRESSES.map((entry) => [`${entry.chain}:${entry.name}`, entry.address.toLowerCase()]),
    );
    for (const entry of siteEntries) {
      const key = `${entry.chain}:${entry.name}`;
      expect(generated.get(key), key).toBe(entry.address.toLowerCase());
    }
    expect(new Set(siteEntries.map((e) => `${e.chain}:${e.name}`)).size).toBe(generated.size);
  });
});
