let compositionData;
let currentIndices;
let layoutContainer;
let videoIdCounter = 0; // Counter for unique video element IDs
const GENERATE_PREVIEW_LAST_REQUEST_KEY = "generatePreview:lastRequestAt";
const GENERATE_PREVIEW_MIN_INTERVAL_MS = 3000;

function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

async function waitForGeneratePreviewRateLimitSlot() {
  try {
    const lastRequestAt = Number(
      localStorage.getItem(GENERATE_PREVIEW_LAST_REQUEST_KEY) || "0",
    );
    const now = Date.now();
    const waitMs = Math.max(
      0,
      lastRequestAt + GENERATE_PREVIEW_MIN_INTERVAL_MS - now,
    );

    if (waitMs > 0) {
      await sleep(waitMs);
    }

    localStorage.setItem(GENERATE_PREVIEW_LAST_REQUEST_KEY, String(Date.now()));
  } catch {
    await sleep(GENERATE_PREVIEW_MIN_INTERVAL_MS);
  }
}

document.addEventListener("DOMContentLoaded", function () {
  layoutContainer = document.getElementById("layout-container");
  if (!layoutContainer) {
    console.error("Error: layout-container element not found.");
    return;
  }

  window.onload = async function () {
    let baseUrl = "https://back.disploy.com/api/NewScreen/GeneratePreview";
    let storedData;

    for (let attempt = 1; attempt <= 3; attempt++) {
      await waitForGeneratePreviewRateLimitSlot();

      try {
        const response = await axios.post(baseUrl, {
          macid: localStorage.getItem("machineId"),
        });
        storedData = response.data;
        break;
      } catch (error) {
        const isRateLimited = error?.response?.status === 429;
        if (isRateLimited && attempt < 3) {
          console.warn(
            `GeneratePreview 429 (attempt ${attempt}/3). Retrying in 3 seconds...`,
          );
          await sleep(GENERATE_PREVIEW_MIN_INTERVAL_MS);
          continue;
        }

        console.error(
          "Failed to fetch GeneratePreview for composition:",
          error,
        );
      }
    }

    if (!storedData) {
      console.error("No data found in localStorage.");
      if (typeof loaderManager !== "undefined") {
        loaderManager.hide();
      }
      return;
    }

    const parsedData = storedData;
    compositionData = parsedData?.myComposition?.[0]?.compositionPossition;

    console.log("📦 Composition data loaded:", {
      hasMyComposition: !!parsedData?.myComposition,
      compositionCount: parsedData?.myComposition?.length,
      hasCompositionPossition:
        !!parsedData?.myComposition?.[0]?.compositionPossition,
      compositionPossitionLength:
        parsedData?.myComposition?.[0]?.compositionPossition?.length,
      compositionData: compositionData,
    });

    if (
      !compositionData ||
      !Array.isArray(compositionData) ||
      compositionData.length === 0
    ) {
      console.error("Invalid or empty composition data.", {
        compositionData,
        fullData: parsedData,
      });
      if (typeof loaderManager !== "undefined") {
        loaderManager.hide();
      }
      return;
    }

    currentIndices = Array(compositionData.length).fill(0);
    initLayout();

    // Hide loader after layout is initialized
    if (typeof loaderManager !== "undefined") {
      loaderManager.hide();
    }
  };

  window.onresize = initLayout;
});

function buildContent(schedule, sequenceIndex) {
  const contentBox = document.querySelector(`#content-box-${sequenceIndex}`);

  // Clean up existing media before replacing
  const existingVideos = contentBox.querySelectorAll("video");
  existingVideos.forEach((video) => {
    try {
      video.pause();
      video.src = "";
      video.load();
    } catch (e) {
      console.log("Error cleaning up video:", e.message);
    }
  });

  contentBox.innerHTML = renderMedia(schedule);
  observeMedia(contentBox);
}

function renderSchedules(schedules, sequenceIndex) {
  console.log("Rendering schedules for sequence index:", sequenceIndex);
  if (schedules.length === 0) return;

  const currentIndex = currentIndices[sequenceIndex];
  const schedule = schedules[currentIndex];
  buildContent(schedule, sequenceIndex);

  const duration = schedule.durationInSecond * 1000;
  const startTime = performance.now();

  function scheduleNext() {
    const elapsed = performance.now() - startTime;
    if (elapsed >= duration) {
      currentIndices[sequenceIndex] = (currentIndex + 1) % schedules.length;
      renderSchedules(schedules, sequenceIndex);
    } else {
      requestAnimationFrame(scheduleNext);
    }
  }
  requestAnimationFrame(scheduleNext);
}

function renderApp(appUrl) {
  console.log("Rendering app iframe with URL:", appUrl);

  // Basic URL validation
  if (!appUrl || typeof appUrl !== "string") {
    console.error("App URL must be a non-empty string");
    return '<div style="display: flex; align-items: center; justify-content: center; height: 100%; color: white;">App URL must be a non-empty string</div>';
  }

  try {
    // Decode HTML entities (e.g., &amp; to &) using textarea for proper URL decoding
    // This is safe because textarea doesn't execute scripts and we validate the URL afterward
    const textarea = document.createElement("textarea");
    textarea.innerHTML = appUrl;
    const decodedUrl = textarea.value;

    console.log("Decoded URL:", decodedUrl);

    // Validate URL format and protocol
    const url = new URL(decodedUrl);
    if (url.protocol !== "http:" && url.protocol !== "https:") {
      console.error("Invalid URL protocol:", url.protocol);
      return '<div style="display: flex; align-items: center; justify-content: center; height: 100%; color: white;">Only HTTP/HTTPS URLs are allowed</div>';
    }

    // Create iframe using DOM methods for security
    const iframe = document.createElement("iframe");
    iframe.setAttribute("src", url.href);
    iframe.setAttribute("allowfullscreen", "true");
    iframe.setAttribute("loading", "lazy");
    iframe.setAttribute(
      "allow",
      "autoplay; fullscreen; camera; microphone; geolocation",
    );
    iframe.style.cssText =
      "width: 100%; height: 100%; border: none; position: absolute; left: 0; top: 0;";

    return iframe.outerHTML;
  } catch (e) {
    console.error("Malformed app URL:", appUrl, e);
    return '<div style="display: flex; align-items: center; justify-content: center; height: 100%; color: white;">Malformed app URL</div>';
  }
}

function renderMedia(schedule) {
  console.log("Rendering media for schedule:", schedule);
  if (schedule.apps && schedule.apps.trim() !== "") {
    console.log("✅ Rendering app iframe:", schedule.apps);
    return renderApp(schedule.apps);
  }

  const mediaType = schedule.mediaType.toLowerCase();

  const screenResolution =
    schedule.screenResolutionName?.toLowerCase() == "fit"
      ? "fill"
      : schedule.screenResolutionName?.toLowerCase() || "cover";

  switch (mediaType) {
    case "text":
      return `
              <marquee 
                class="marquee"
                behavior="scroll" 
                direction="${schedule.direction === "LTR" ? "right" : "left"}" 
                scrollamount="10"
              >
                ${schedule.fileType}
              </marquee>
            `;

    case "youtube":
      const videoId = extractVideoId(schedule.fileType);
      return `<iframe src="https://www.youtube.com/embed/${videoId}?autoplay=1&controls=0&mute=${
        schedule.isMute ? 1 : 0
      }&loop=1&playlist=${videoId}" allowfullscreen loading="lazy"></iframe>`;

    case "image":
      if (schedule.screenResolutionName?.toLowerCase() === "zoom") {
        return `<img
                  src="${schedule.fileType}"
                  style="width: 100%; height: 100%; object-fit: ${screenResolution};
                         transform: scale(1.2);
                         transform-origin: center;
                         overflow: hidden;">`;
      } else {
        return `<img
                  src="${schedule.fileType}"
                  style="width: 100%; height: 100%; object-fit: ${
                    screenResolution.toUpperCase() == "NONE"
                      ? "contain"
                      : screenResolution
                  };">`;
      }

    case "video":
      if (schedule.screenResolutionName?.toLowerCase() === "zoom") {
        return `<video 
                    id="video-${++videoIdCounter}" 
                    class="video-js vjs-default-skin" 
                    autoplay 
                    preload="auto"
                    muted 
                    loop 
                    playsinline
                    poster=${schedule.thumbImage}
                    style="width: 100%; height: 100%; object-fit: ${screenResolution};
                           transform: scale(1.2);
                           transform-origin: center;
                           overflow: hidden;"
                    data-setup='{}'>
                    <source src="${schedule.fileType}" type="video/mp4">
                    Your browser does not support the video tag.
                  </video>`;
      } else {
        return `<video 
                id="video-${++videoIdCounter}" 
                class="video-js vjs-default-skin" 
                autoplay 
                preload="auto"
                muted 
                loop 
                playsinline
                poster=${schedule.thumbImage}
                style="width: 100%; height: 100%; object-fit: ${
                  screenResolution.toUpperCase() == "NONE"
                    ? "contain"
                    : screenResolution
                };"
                data-setup='{}'>
                <source src="${schedule.fileType}" type="video/mp4">
                Your browser does not support the video tag.
              </video>`;
      }

    case "pdf":
    case "docx":
    case "ppt":
    case "excel":
      return createIframe(schedule);

    default:
      console.warn(`⚠️ Unsupported media type: ${mediaType}`, schedule);
      return `<div style="display: flex; align-items: center; justify-content: center; height: 100%; color: white; font-size: 20px;">Unsupported media type: ${mediaType}</div>`;
  }
}

function createIframe(schedule) {
  const iframe = document.createElement("iframe");

  iframe.src = `https://docs.google.com/viewer?embedded=true&url=${schedule.fileType}`;

  if (schedule.screenResolutionName?.toLowerCase() === "zoom") {
    iframe.style = `
      width: 100%; 
      height: 100%; 
      position: absolute; 
      left: 0; 
      top: 0; 
      object-fit: cover; 
      transform: scale(1.2); 
      transform-origin: center; 
      overflow: hidden; 
      border: none;`;
  } else {
    iframe.style = `
      width: 100%; 
      height: 100%; 
      position: absolute; 
      left: 0; 
      top: 0; 
      object-fit: cover; 
      border: none;`;
  }

  iframe.allowFullscreen = true;

  iframe.onerror = () => {
    console.error("Iframe failed to load. Reloading...");
    iframe.src = iframe.src;
  };

  if (schedule.isScroll) {
    console.log("Scrolling iframe...", document.body.scrollHeight);
    let scrollAmount =
      schedule.numberOfPages > 0 ? schedule.numberOfPages * 4 * 40 : 100;

    const scrollInterval = schedule.scrollPerSec * 1000;

    const scrollWebsite = () => {
      try {
        console.log("Scrolling website...", scrollAmount);
        document.body.scrollTo(0, scrollAmount);
      } catch (err) {
        console.error("Error scrolling website:", err);
      }
    };

    setInterval(scrollWebsite, scrollInterval);
  }

  return iframe.outerHTML;
}

function extractVideoId(url) {
  const regExp = /^.*(?:youtu.be\/|v\/|embed\/|watch\?v=)([^#&?]*).*/;
  const match = url.match(regExp);
  return match && match[1].length === 11 ? match[1] : null;
}

function initLayout() {
  if (!compositionData || !Array.isArray(compositionData)) {
    console.warn("initLayout called but compositionData not ready yet");
    return;
  }

  layoutContainer.innerHTML = "";
  console.log("Initializing layout with composition data:", compositionData);
  compositionData.forEach((box, index) => {
    const left = (box.left / 100) * window.innerWidth;
    const top = (box.top / 100) * window.innerHeight;
    const width = (box.width / 100) * window.innerWidth;
    const height = (box.height / 100) * window.innerHeight;

    const contentBox = document.createElement("div");
    contentBox.id = `content-box-${index}`;
    contentBox.classList.add("content-box");
    contentBox.style.position = "absolute";
    contentBox.style.left = `${left}px`;
    contentBox.style.top = `${top}px`;
    contentBox.style.width = `${width}px`;
    contentBox.style.height = `${height}px`;

    layoutContainer.appendChild(contentBox);

    renderSchedules(box.schedules, index);
  });
}

function observeMedia(element) {
  const observer = new IntersectionObserver(
    (entries) => {
      entries.forEach((entry) => {
        const video = entry.target.querySelector("video");
        if (!video) return;

        if (entry.isIntersecting) {
          // Play video with proper promise handling
          const playPromise = video.play();
          if (playPromise !== undefined) {
            playPromise
              .then(() => {
                // Video playback started successfully
              })
              .catch((error) => {
                // Auto-play was prevented or interrupted
                // Common errors: NotAllowedError, AbortError
                if (error.name !== "AbortError") {
                  console.log("Video play prevented:", error.message);
                }
              });
          }
        } else {
          // Pause video safely
          try {
            if (video && !video.paused) {
              video.pause();
            }
          } catch (e) {
            console.log("Error pausing video:", e.message);
          }
        }
      });
    },
    {
      threshold: 0.5,
    },
  );

  observer.observe(element);
}
