(function () {
  "use strict";

  var config = window.PDTFirewallDiagnostics || {};

  function getRoot(button) {
    return button.closest(".pdt-firewall-diagnostics");
  }

  function getResults(root) {
    return root ? root.querySelector(".pdt-firewall-diagnostics__results") : null;
  }

  function setButtonsBusy(root, busy) {
    if (!root) {
      return;
    }

    var buttons = root.querySelectorAll(".pdt-firewall-diagnostics-run, .pdt-firewall-diagnostics-clear");
    buttons.forEach(function (button) {
      button.disabled = !!busy;
      button.classList.toggle("is-busy", !!busy);
    });
  }

  function createNode(tag, className, text) {
    var node = document.createElement(tag);

    if (className) {
      node.className = className;
    }

    if (typeof text !== "undefined") {
      node.textContent = text;
    }

    return node;
  }

  function post(action, data) {
    var formData = new window.FormData();

    formData.append("action", action);
    formData.append("nonce", config.nonce || "");

    Object.keys(data || {}).forEach(function (key) {
      formData.append(key, data[key]);
    });

    return window.fetch(config.ajaxUrl, {
      method: "POST",
      credentials: "same-origin",
      body: formData
    }).then(function (response) {
      return response.json();
    });
  }

  function renderMessage(results, message, type) {
    if (!results) {
      return;
    }

    results.innerHTML = "";
    results.appendChild(createNode("div", "pdt-firewall-diagnostics-message is-" + type, message));
  }

  function renderSummary(results, summary) {
    var summaryNode = createNode("div", "pdt-firewall-diagnostics-summary");
    var labels = config.i18n && config.i18n.summary ? config.i18n.summary : {};
    var items = [
      [labels.total || "Total", summary.total],
      [labels.passed || "Passed", summary.passed],
      [labels.failed || "Failed", summary.failed],
      [labels.mode || "Mode", summary.mode],
      [labels.runtime || "Runtime", summary.runtime + " ms"]
    ];

    items.forEach(function (item) {
      var badge = createNode("span", "pdt-firewall-diagnostics-summary__item");
      badge.appendChild(createNode("strong", "", item[0]));
      badge.appendChild(document.createTextNode(String(item[1])));
      summaryNode.appendChild(badge);
    });

    results.appendChild(summaryNode);
  }

  function renderDetails(details) {
    var list = createNode("ul", "pdt-firewall-diagnostics-details");
    var normalized = Array.isArray(details) ? details : [String(details || "")];

    normalized.forEach(function (detail) {
      list.appendChild(createNode("li", "", detail));
    });

    return list;
  }

  function renderGroup(group) {
    var groupNode = createNode("section", "pdt-firewall-diagnostics-group");
    var title = createNode("h4", "", group.title || "");
    var table = createNode("table", "widefat striped pdt-firewall-diagnostics-table");
    var thead = document.createElement("thead");
    var headRow = document.createElement("tr");
    var tbody = document.createElement("tbody");
    var columns = config.i18n && config.i18n.columns ? config.i18n.columns : {};

    [
      columns.status || "Status",
      columns.test || "Test",
      columns.expected || "Expected",
      columns.actual || "Actual",
      columns.details || "Details"
    ].forEach(function (heading) {
      headRow.appendChild(createNode("th", "", heading));
    });

    thead.appendChild(headRow);
    table.appendChild(thead);

    (group.tests || []).forEach(function (test) {
      var row = document.createElement("tr");
      var status = createNode("span", "pdt-firewall-diagnostics-status is-" + test.status, test.status);

      [
        status,
        createNode("span", "", test.name || ""),
        createNode("span", "", test.expected || ""),
        createNode("span", "", test.actual || ""),
        renderDetails(test.details || [])
      ].forEach(function (cellContent) {
        var cell = document.createElement("td");
        cell.appendChild(cellContent);
        row.appendChild(cell);
      });

      tbody.appendChild(row);
    });

    table.appendChild(tbody);
    groupNode.appendChild(title);
    groupNode.appendChild(table);

    return groupNode;
  }

  function renderResults(results, payload) {
    results.innerHTML = "";

    if (!payload || !payload.summary) {
      renderMessage(results, config.i18n && config.i18n.failed ? config.i18n.failed : "Diagnostics could not be completed.", "error");
      return;
    }

    renderSummary(results, payload.summary);

    (payload.groups || []).forEach(function (group) {
      results.appendChild(renderGroup(group));
    });
  }

  function runDiagnostics(button) {
    var root = getRoot(button);
    var results = getResults(root);
    var suite = button.getAttribute("data-suite") || "all";

    setButtonsBusy(root, true);
    renderMessage(results, config.i18n && config.i18n.running ? config.i18n.running : "Running diagnostics...", "info");

    post(config.runAction, { suite: suite }).then(function (response) {
      if (!response || !response.success) {
        renderMessage(results, response && response.data && response.data.message ? response.data.message : config.i18n.failed, "error");
        return;
      }

      renderResults(results, response.data);
    }).catch(function () {
      renderMessage(results, config.i18n && config.i18n.failed ? config.i18n.failed : "Diagnostics could not be completed.", "error");
    }).finally(function () {
      setButtonsBusy(root, false);
    });
  }

  function clearDiagnostics(button) {
    var root = getRoot(button);
    var results = getResults(root);

    setButtonsBusy(root, true);

    post(config.clearAction, {}).then(function (response) {
      renderMessage(
        results,
        response && response.data && response.data.message ? response.data.message : (config.i18n && config.i18n.cleared ? config.i18n.cleared : "Firewall diagnostics test data cleared."),
        response && response.success ? "success" : "error"
      );
    }).catch(function () {
      renderMessage(results, config.i18n && config.i18n.failed ? config.i18n.failed : "Diagnostics could not be completed.", "error");
    }).finally(function () {
      setButtonsBusy(root, false);
    });
  }

  document.addEventListener("click", function (event) {
    var runButton = event.target.closest(".pdt-firewall-diagnostics-run");
    var clearButton = event.target.closest(".pdt-firewall-diagnostics-clear");

    if (runButton) {
      event.preventDefault();
      runDiagnostics(runButton);
      return;
    }

    if (clearButton) {
      event.preventDefault();
      clearDiagnostics(clearButton);
    }
  });
}());
