const assert = require("node:assert/strict");
const {
  absoluteUrl,
  clickByTitle,
  clickText,
  fillInput,
  getValue,
  registerAndLoginApi,
  runSmokeTests,
  seedAuthenticatedBrowser,
  uniqueName,
  waitFor,
  withDriver,
  waitForSelector,
  waitForText,
  waitForUrl
} = require("./lib/selenium-smoke");

const tests = [
  {
    name: "campaign management rerenders immediately after campaign and character mutations",
    run: async () => withDriver({}, async (driver) => {
      const username = uniqueName("campaign-refresh");
      const { sessionCookie } = await registerAndLoginApi(username, "Campaign Refresh");
      const campaignName = uniqueName("campaign");
      const characterName = uniqueName("character");
      const updatedCharacterName = uniqueName("character-updated");

      await seedAuthenticatedBrowser(driver, sessionCookie);
      await driver.get(absoluteUrl("/campaigns"));
      await waitForUrl(driver, "/campaigns");
      await waitForText(driver, "Character Management");

      await clickText(driver, "button", "Add campaign", { contains: true });
      await waitForSelector(driver, "#campaign-name");
      await fillInput(driver, "#campaign-name", campaignName);
      await fillInput(driver, "#campaign-ruleset", "d6");
      await clickText(driver, "button", "Create Campaign");

      await waitFor(
        driver,
        () => driver.executeScript(
          (name) => (document.querySelector("#campaign-select")?.textContent || "").includes(name),
          campaignName
        ),
        `Expected campaign ${campaignName} to appear in the campaign selector.`
      );

      const selectedCampaignId = await getValue(driver, "#campaign-select");
      assert.ok(selectedCampaignId, "Expected a selected campaign after campaign creation.");

      await clickText(driver, "button", "Add character", { contains: true });
      await waitForSelector(driver, "#character-create-name");
      await fillInput(driver, "#character-create-name", characterName);
      await clickText(driver, "button", "Create Character");

      await waitFor(
        driver,
        () => driver.executeScript(
          (name) => [...document.querySelectorAll(".management-list strong")].some((element) => element.textContent.includes(name)),
          characterName
        ),
        `Expected character ${characterName} to appear in the campaign roster.`
      );

      await clickByTitle(driver, "Edit character");
      await waitForSelector(driver, "#character-edit-name");
      await fillInput(driver, "#character-edit-name", updatedCharacterName);
      await clickText(driver, "button", "Save Character");

      await waitFor(
        driver,
        () => driver.executeScript(
          (nextName, previousName) => {
            const names = [...document.querySelectorAll(".management-list strong")]
              .map((element) => element.textContent || "");
            return names.some((name) => name.includes(nextName)) && names.every((name) => !name.includes(previousName));
          },
          updatedCharacterName,
          characterName
        ),
        `Expected updated character name ${updatedCharacterName} to appear immediately in the campaign roster.`
      );
    })
  }
];

runSmokeTests(tests).catch((error) => {
  console.error(error.stack || error);
  process.exitCode = 1;
});
