import test from "node:test";
import assert from "node:assert/strict";

await import("./linkedin-connect-dom.js");
const DOM = globalThis.NexusLinkedInConnectDOM;

function element({
  text = "",
  aria = "",
  href = "",
  tagName = "BUTTON",
  closest = null,
  children = [],
} = {}) {
  return {
    innerText: text,
    textContent: text,
    tagName,
    offsetParent: {},
    parentElement: closest,
    getAttribute(name) {
      if (name === "aria-label") return aria || null;
      if (name === "href") return href || null;
      if (name === "aria-hidden") return null;
      return null;
    },
    closest() {
      return closest;
    },
    querySelectorAll() {
      return children;
    },
    querySelector() {
      return children.find((child) => child.tagName === "A") || null;
    },
  };
}

function profileDocument({ controls, rootText = "", otherControls = [] }) {
  const root = element({ text: rootText, children: controls });
  const heading = element({ text: "Jane Doe", closest: root });
  return {
    body: root,
    documentElement: root,
    querySelector(selector) {
      if (selector === "main")
        return {
          querySelector: () => heading,
          querySelectorAll: () => [...controls, ...otherControls],
        };
      return null;
    },
  };
}

test("extracts the canonical profile id from a wrapped search-result URN", () => {
  assert.equal(
    DOM.canonicalProfileId({
      entityUrn:
        "urn:li:fsd_entityResultViewModel:(urn:li:fsd_profile:ACoAAExample_123,SEARCH_SRP,DEFAULT)",
    }),
    "ACoAAExample_123",
  );
});

test("uses the vanity URL instead of LinkedIn's internal ACo profile id", () => {
  assert.equal(
    DOM.publicProfileSlug({
      publicIdentifier: "ACoAAAODW_INTERNAL",
      navigationUrl: "https://www.linkedin.com/in/james-gordon-sandrock/",
    }),
    "james-gordon-sandrock",
  );
  assert.equal(DOM.publicProfileSlug({ publicIdentifier: "ACoAAAODW_INTERNAL" }), "");
});

test("scopes Connect and Pending to the profile owner card", () => {
  const connect = element({ text: "Connect", aria: "Invite Jane Doe to connect" });
  const unrelatedPending = element({ text: "Pending" });
  const doc = profileDocument({ controls: [connect], otherControls: [unrelatedPending] });
  const state = DOM.profileState(doc, "Jane Doe");
  assert.equal(state.connect, connect);
  assert.equal(state.pending, null);
});

test("does not treat a Message button alone as an existing connection", () => {
  const doc = profileDocument({
    controls: [
      element({ text: "Message", aria: "Message Jane Doe" }),
      element({ text: "More", aria: "More actions" }),
    ],
  });
  assert.equal(DOM.profileState(doc, "Jane Doe").alreadyConnected, false);
});

test("finds Connect in a hashed More menu without ARIA menu roles", () => {
  const menu = element({ text: "Connect Follow Report / Block About this member" });
  const connect = element({ text: "Connect", closest: menu });
  connect.closest = () => connect;
  connect.parentElement = menu;
  const unrelated = element({ text: "Connect" });
  unrelated.closest = () => unrelated;
  const doc = { querySelectorAll: () => [unrelated, connect] };

  assert.equal(DOM.findOpenMenuConnect(doc), connect);
});

test("finds an exact profile in sent invitations", () => {
  const row = element({ text: "Jane Doe Sent today Withdraw" });
  const link = element({ text: "Jane Doe", href: "/in/jane-doe/", tagName: "A", closest: row });
  row.querySelector = () => link;
  const doc = { querySelectorAll: (selector) => (selector.includes("a[href") ? [link] : [row]) };
  assert.deepEqual(
    DOM.findSentInvitation(doc, { publicIdentifier: "jane-doe", expectedName: "Jane Doe" }),
    { found: true, matchedBy: "slug", name: "Jane Doe", slug: "jane-doe" },
  );
});

test("rejects a different person in sent invitations", () => {
  const row = element({ text: "Janet Doe Withdraw" });
  const link = element({ text: "Janet Doe", href: "/in/janet-doe/", tagName: "A", closest: row });
  row.querySelector = () => link;
  const doc = { querySelectorAll: (selector) => (selector.includes("a[href") ? [link] : [row]) };
  assert.equal(
    DOM.findSentInvitation(doc, { publicIdentifier: "jane-doe", expectedName: "Jane Doe" }).found,
    false,
  );
});
