export function insitella() {
  const apiBaseURL = "http://192.168.10.152";
  const formatDate = (date) => date.toISOString().split("T")[0];
  const generateUserName = (length) => {
    const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    return Array.from({ length }, () =>
      chars.charAt(crypto.getRandomValues(new Uint32Array(1))[0] % chars.length)
    ).join("");
  };
  const saveUserNameInSession = (value) => sessionStorage.setItem("insitella_usernames", JSON.stringify(value));
  const saveUserEventInSession = (value) => sessionStorage.setItem("insitella_userevents", JSON.stringify(value));
  const getCookie = (cookieName) => {
    return  document.cookie
      .split(";")
      .map((c) => c.trim())
      .find((c) => c.startsWith(`${cookieName}=`))
      ?.split("=")[1] || null;
  };
  const createCookie = (name, value, hours) => {
    const exp = new Date(Date.now() + hours * 60 * 60 * 1000);
    document.cookie = `${name}=${value};expires=${exp.toUTCString()};path=/`;
  };
  const detectDeviceType = () => {
    const ua = navigator.userAgent.toLowerCase();
    return /ipad|tablet|playbook|silk/i.test(ua)
      ? "tablet"
      : /mobile|iphone|ipod|blackberry|opera mini|iemobile|windows phone|trident|opera mobi|mobilesafari|htc|nokia|symbian|samsung|lg|mot/i.test(ua)
      ? "mobile"
      : "pc";
  };
  const determineCurrentScreen = () => window.location.href.split("/").pop();
  const closeCookiePopup = () => document.getElementById("cookiePopup")?.remove();
  const handleCookieOnAcceptance = async () => {
    closeCookiePopup();
    if (!navigator.geolocation) return;
    const getPosition = () =>
      new Promise((resolve, reject) =>
        navigator.geolocation.getCurrentPosition(resolve, reject)
      );
    try {
      const {
        coords: { latitude, longitude },
      } = await getPosition();
      const url = `https://nominatim.openstreetmap.org/reverse?lat=${latitude}&lon=${longitude}&format=json`;
      const response = await fetch(url);
      const locationData = await response.json();
      const userType = sessionStorage.getItem("insitella_usernames") ? "Authenticated" : "Anonymous";
      const deviceType = getCookie("deviceType");
      const userInfo = {
        ip: ipAddress,
        userName: generateUserName(5),
        userType,
        browserName,
        formattedDate,
        formattedTime,
        clientName,
        deviceType,
      };
      const locationInfo = {
        clientName,
        latitude: latitude.toString(),
        longitude: longitude.toString(),
        cityName: locationData.address?.city || locationData.address?.town || locationData.address?.village || "",
        country: locationData.address?.country || ""
      };
      const deviceInfo = {
        clientName,
        DeviceName: deviceType,
      };
      const configRes = await fetch(`${apiBaseURL}/config`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ userInfo }),
      });
      const { _id, serverUpdateTime } = await configRes.json();
      createCookie("serverUpdateTime", serverUpdateTime, 30);
      createCookie("userId", _id, 30);
      locationInfo._id = _id;
      deviceInfo._id = _id;
      await fetch(`${apiBaseURL}/saveMapData`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(locationInfo),
      });
      await fetch(`${apiBaseURL}/saveDeviceData`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(deviceInfo),
      });
      createCookie("cookieAccepted", "true", 24);
    } catch (err) { }
  };
  const htmlTemplate = `
  <div id="cookiePopup" style="position: fixed; inset: 0; background: rgba(0, 0, 0, 0.5); display: flex; justify-content: center; align-items: center; z-index: 9999;">
    <div class="wrapper" style="background: #fff; position: fixed; bottom: 20px; left: 50px; max-width: 500px; border-radius: 15px; text-align: center; border: 1px solid #493179; padding: 25px; box-shadow: 0 0 18px rgba(0, 0, 0, 0.13);">
      <img src="../../assets/img/cookie.png" alt="Cookie" style="max-width: 90px;">
      <div class="content" style="margin-top: 10px;">
        <h1 style="font-size: 25px; font-weight: 600;">GDPR Compliance Notice</h1>
        <h5>What data do we collect?</h5>
        <ul style="list-style-type: disc; text-align: left;">
          <li>Personal information such as name, email, and location when you sign up or interact with our platform.</li>
          <li>Usage patterns, preferences, and interactions to enhance your experience.</li>
        </ul>
        <div class="buttons" style="display: flex; justify-content: center;">
          <button id="cookieCancelBtn" style="padding: 10px 20px; margin: 0 5px; border: none; font-size: 16px; font-weight: 500; border-radius: 5px; cursor: pointer; background: #eee; color: #333;">Cancel</button>
          <button id="cookieAcceptBtn" style="padding: 10px 20px; margin: 0 5px; border: none; font-size: 16px; font-weight: 500; border-radius: 5px; cursor: pointer; background: #493179; color: #fff;">Accept</button>
        </div>
      </div>
    </div>
  </div>
  `;
  const currentDate = new Date();
  const formattedDate = formatDate(currentDate);
  const formattedTime = [currentDate.getHours(), currentDate.getMinutes(), currentDate.getSeconds()].map((n) => n.toLocaleString()).join(":");
  const browserNameMap = {
    Firefox: "Mozilla Firefox",
    "Edg/": "Microsoft Edge",
    Chrome: "Google Chrome",
    Safari: "Apple Safari",
    Opera: "Opera",
    MSIE: "Internet Explorer",
    "Trident/": "Internet Explorer",
  };
  const userAgent = navigator.userAgent;
  const browserName = Object.keys(browserNameMap).find((key) => userAgent.includes(key)) || "Unknown Browser";
  const clientName = document.querySelector("title")?.innerHTML || "";
  let ipAddress = "";
  let pageName = "";
  let newPageName = "";
  let isPageChanged = false;
  if (!getCookie("deviceType")) createCookie("deviceType", detectDeviceType(), 24);
  document.addEventListener("DOMContentLoaded", () => {
    fetch("https://api.ipify.org?format=json")
      .then((res) => res.json())
      .then(({ ip }) => {
        ipAddress = ip;
        const deviceType = getCookie("deviceType");
        const userDetail = {
          userInfo: [{
            ip,
            userName: generateUserName(5),
            browserName,
            dates: formattedDate,
            time: formattedTime,
            deviceType,
            clientName,
          }],
        };
        const stored = JSON.parse(sessionStorage.getItem("insitella_usernames"));
        if (stored?.userInfo?.[0]?.ip !== ip) saveUserNameInSession(userDetail);
      })
      .catch((err) => {});
    if (!getCookie("cookieAccepted")) {
      const container = document.createElement("div");
      container.innerHTML = htmlTemplate.trim();
      document.body.appendChild(container.firstChild);
      document.getElementById("cookieAcceptBtn")?.addEventListener("click", handleCookieOnAcceptance);
      document.getElementById("cookieCancelBtn")?.addEventListener("click", closeCookiePopup);
    }
    pageName = determineCurrentScreen();
    new MutationObserver(() => {
      const currentUrl = window.location.href;
      newPageName = currentUrl.substring(currentUrl.lastIndexOf("/") + 1);
      if (newPageName !== pageName) isPageChanged = true;
    }).observe(document.body, { subtree: true, childList: true });
  });
  (function () {
    let clickData = {};
    let clickCounts = {};
    let requestPayload = null;
    let isResponseToDB = false;
    let isSending = false;
    const userDetail = {};
    const dataKeysToClear = ["insitella_userevents", "insitella_usernames"];
    const updateClickCount = (text, type) => {
      const key = `${type}${text}`;
      clickCounts[key] = (clickCounts[key] || 0) + 1;
      const displayElement = document.getElementById(`${key}_click_count`);
      if (displayElement) displayElement.textContent = clickCounts[key];
      if (!clickData[pageName]) clickData[pageName] = {};
      clickData[pageName][key] = clickCounts[key];
      userDetail.userEvents = [{ ...clickData }];
      clickData = {};
      clickCounts = {};
      const existingUserEventsInSession = sessionStorage.getItem("insitella_userevents");
      const newUserEvents = JSON.parse(JSON.stringify(userDetail));
      if (!existingUserEventsInSession) {
        newUserEvents.userEvents[0].date = formattedDate;
        saveUserEventInSession([newUserEvents]);
        requestPayload = JSON.stringify(newUserEvents.userEvents);
        isResponseToDB = true;
      } else {
        let stored = JSON.parse(existingUserEventsInSession);
        const existingEvents = stored[0].userEvents;
        newUserEvents.userEvents.forEach((event, index) => {
          const targetEvent = existingEvents[index] || {};
          const screen = Object.keys(event)[0];
          if (!targetEvent[screen]) targetEvent[screen] = {};
          for (const key in event[screen]) {
            targetEvent[screen][key] = (targetEvent[screen][key] || 0) + event[screen][key];
          }
          existingEvents[index] = targetEvent;
        });
        existingEvents[0].date = formattedDate;
        saveUserEventInSession([{ ...userDetail, userEvents: existingEvents }]);
        requestPayload = JSON.stringify(existingEvents);
        isResponseToDB = true;
      }
    };
    const getParentContent = (el, selector) => {
      let content = el.textContent.trim();
      let parent = el.parentElement.closest(selector);
      while (parent) {
        content = parent.textContent.trim();
        parent = parent.parentElement.closest(selector);
      }
      return content;
    };
    document.addEventListener("click", (event) => {
      const target = event.target;
      if (target.closest("button")) {
        updateClickCount(getParentContent(target, "button"), "btn_");
        if (isPageChanged) pageName = newPageName;
      } else if (target.closest("a")) {
        updateClickCount(getParentContent(target, "a"), "link_");
        if (isPageChanged) pageName = newPageName;
      }
    });
  const sendUserEventData = async () => {
      const existingUserEventsInSession = sessionStorage.getItem("insitella_userevents");
      if (isSending || !isResponseToDB || !requestPayload || !existingUserEventsInSession) return;
      
      isSending = true;
      const userId = getCookie("userId");
      try {
        dataKeysToClear.forEach((key) => sessionStorage.removeItem(key));
        const response = await fetch(`${apiBaseURL}/updateUserEvents/${userId}`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: requestPayload,
        });
        if (!response.ok) throw new Error(`Failed to send event data: ${response.status}`);
        const res = await response.json();
        const existingUserEventsInSession = sessionStorage.getItem("insitella_userevents");
        if (!existingUserEventsInSession) {
          isResponseToDB = false;
          requestPayload = null;
        }
      } catch (err) {
        throw new Error(`Error sending user event data: ${err.message}`);
      } finally {
        isSending = false;
      }
    };
    let bootstrapTimer = null;
    let eventDataTimer = null;
    const startSendingEventData = () => {
      const interval = getCookie("serverUpdateTime");
      if (interval) {
        if (eventDataTimer) clearInterval(eventDataTimer);
        eventDataTimer = setInterval(sendUserEventData, parseInt(interval));
        if (bootstrapTimer) {
          clearInterval(bootstrapTimer);
          bootstrapTimer = null;
        }
      }
    };
    sendUserEventData();
    bootstrapTimer = setInterval(startSendingEventData, 1000);
  })();
}

module.exports = { insitella };