(function () {
  if (window.GIAComposePanelCore) {
    return;
  }

  const PANEL_SELECTOR = ".compose-shell[data-compose-panel='1']";
  window.giaComposePanels = window.giaComposePanels || {};

  const collectPanels = function (root) {
    const panels = [];
    if (!root) {
      return panels;
    }
    if (root.matches && root.matches(PANEL_SELECTOR)) {
      panels.push(root);
    }
    if (root.querySelectorAll) {
      root.querySelectorAll(PANEL_SELECTOR).forEach(function (panel) {
        panels.push(panel);
      });
    }
    return panels;
  };

  const toInt = function (value) {
    const parsed = parseInt(value || "0", 10);
    return Number.isFinite(parsed) ? parsed : 0;
  };

  const parseJsonSafe = function (value, fallback) {
    try {
      return JSON.parse(String(value || ""));
    } catch (_err) {
      return fallback;
    }
  };

  const createNode = function (tagName, className, text) {
    const node = document.createElement(tagName);
    if (className) {
      node.className = className;
    }
    if (text !== undefined && text !== null) {
      node.textContent = String(text);
    }
    return node;
  };

  const normalizeSnippet = function (value) {
    const compact = String(value || "").replace(/\s+/g, " ").trim();
    if (!compact) {
      return "(no text)";
    }
    if (compact.length <= 120) {
      return compact;
    }
    return compact.slice(0, 117).trimEnd() + "...";
  };

  const titleCase = function (value) {
    const raw = String(value || "").trim().toLowerCase();
    if (!raw) {
      return "";
    }
    if (raw === "whatsapp") {
      return "WhatsApp";
    }
    if (raw === "xmpp") {
      return "XMPP";
    }
    return raw.charAt(0).toUpperCase() + raw.slice(1);
  };

  const normalizeIdentifierForService = function (service, identifier) {
    const serviceKey = String(service || "").trim().toLowerCase();
    const raw = String(identifier || "").trim();
    if (serviceKey === "whatsapp" && raw.includes("@")) {
      return raw.split("@", 1)[0].trim();
    }
    return raw;
  };

  const buildComposeUrl = function (renderMode, service, identifier, personId) {
    const serviceKey = String(service || "").trim().toLowerCase();
    const identifierValue = normalizeIdentifierForService(serviceKey, identifier);
    if (!serviceKey || !identifierValue) {
      return "";
    }
    const params = new URLSearchParams();
    params.set("service", serviceKey);
    params.set("identifier", identifierValue);
    if (personId) {
      params.set("person", String(personId || "").trim());
    }
    return (renderMode === "page" ? "/compose/page/" : "/compose/widget/")
      + "?"
      + params.toString();
  };

  const parseServiceMap = function (optionNode) {
    const fallbackService = String(
      (optionNode && optionNode.dataset && optionNode.dataset.service) || ""
    ).trim().toLowerCase();
    const fallbackIdentifier = String((optionNode && optionNode.value) || "").trim();
    const fallback = {};
    if (fallbackService && fallbackIdentifier) {
      fallback[fallbackService] = fallbackIdentifier;
    }
    if (!optionNode || !optionNode.dataset) {
      return fallback;
    }
    const parsed = parseJsonSafe(optionNode.dataset.serviceMap || "{}", fallback);
    if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
      return fallback;
    }
    const normalized = {};
    Object.keys(parsed).forEach(function (key) {
      const serviceKey = String(key || "").trim().toLowerCase();
      const identifierValue = String(parsed[key] || "").trim();
      if (serviceKey && identifierValue) {
        normalized[serviceKey] = identifierValue;
      }
    });
    return Object.keys(normalized).length ? normalized : fallback;
  };

  window.GIAComposePanelCore = {
    PANEL_SELECTOR: PANEL_SELECTOR,
    buildComposeUrl: buildComposeUrl,
    collectPanels: collectPanels,
    createNode: createNode,
    normalizeIdentifierForService: normalizeIdentifierForService,
    normalizeSnippet: normalizeSnippet,
    parseJsonSafe: parseJsonSafe,
    parseServiceMap: parseServiceMap,
    titleCase: titleCase,
    toInt: toInt,
  };
})();
