const KIOSK_SKELETON_MIN_MS = 300;
const KIOSK_SKELETON_EXIT_MS = 160;

const GRID_CARD_INNER = `
  <div class="dashboard-skeleton-bar dashboard-skeleton-bar--kiosk-title"></div>
  <div class="kiosk-skeleton-info">
    <div class="dashboard-skeleton-bar dashboard-skeleton-bar--kiosk-meta"></div>
    <div class="dashboard-skeleton-bar dashboard-skeleton-bar--kiosk-meta"></div>
  </div>`;

const GROUP_ITEM_INNER = `
  <div class="dashboard-skeleton-bar dashboard-skeleton-bar--title"></div>
  <div class="dashboard-skeleton-bar dashboard-skeleton-bar--meta"></div>`;

export function buildGridSkeletonCards(rowCount = 4) {
  return Array.from({ length: rowCount }, () =>
    `<div class="dispenser-card kiosk-skeleton-card" aria-hidden="true">${GRID_CARD_INNER}</div>`
  ).join("");
}

export function buildDispenserGridSkeletonHtml(rowCount = 4) {
  return buildGridSkeletonCards(rowCount);
}

export function buildPeriodRecipeGridSkeletonHtml(rowCount = 4) {
  return buildGridSkeletonCards(rowCount);
}

export function buildUnloadingGroupsSkeletonHtml(rowCount = 3) {
  const items = Array.from({ length: rowCount }, () =>
    `<div class="kiosk-skeleton-group-item">${GROUP_ITEM_INNER}</div>`
  ).join("");
  return `<div class="kiosk-skeleton-groups" data-skeleton-variant="groups" aria-busy="true" aria-label="Загрузка групп выгрузки">${items}</div>`;
}

export function buildDuplicatePanelSkeletonHtml() {
  return `<div class="kiosk-skeleton-panel" data-skeleton-variant="duplicate" aria-busy="true" aria-label="Загрузка данных">
    <div class="kiosk-skeleton-recipe-header">
      <div class="dashboard-skeleton-bar dashboard-skeleton-bar--title"></div>
      <div class="dashboard-skeleton-bar dashboard-skeleton-bar--subtitle"></div>
    </div>
    <div class="dashboard-skeleton-bar kiosk-skeleton-component-name"></div>
    <div class="dashboard-skeleton-bar kiosk-skeleton-weight-hero"></div>
  </div>`;
}

export function buildRecipeIngredientsSkeletonHtml(rowCount = 6) {
  const rows = Array.from({ length: rowCount }, () =>
    `<div class="kiosk-skeleton-table-row">
      <div class="dashboard-skeleton-bar"></div>
      <div class="dashboard-skeleton-bar"></div>
    </div>`
  ).join("");
  return `<div class="kiosk-skeleton-table" data-skeleton-variant="ingredients" aria-busy="true" aria-label="Загрузка ингредиентов">${rows}</div>`;
}

function prefersReducedMotion() {
  return globalThis.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches;
}

function isGridSkeletonHost(container) {
  if (!container) return false;
  return (
    container.getAttribute("aria-busy") === "true" &&
    container.querySelector(":scope > .kiosk-skeleton-card") != null
  );
}

function findSkeletonRoot(container) {
  if (!container) return null;
  if (isGridSkeletonHost(container)) return container;
  return container.querySelector(
    ":scope > .kiosk-skeleton-groups, :scope > .kiosk-skeleton-table, :scope > .kiosk-skeleton-panel"
  );
}

export function mountKioskSkeleton(container, html, label) {
  if (!container) return performance.now();
  container.innerHTML = html;
  container.classList.remove("kiosk-skeleton-host--exit");
  if (container.querySelector(":scope > .kiosk-skeleton-card")) {
    container.setAttribute("aria-busy", "true");
    if (label) container.setAttribute("aria-label", label);
  }
  return performance.now();
}

export async function awaitKioskSkeletonMin(startedAt, minMs = KIOSK_SKELETON_MIN_MS) {
  const elapsed = performance.now() - startedAt;
  const rest = minMs - elapsed;
  if (rest > 0) {
    await new Promise((resolve) => setTimeout(resolve, rest));
  }
}

async function fadeOutSkeleton(skel) {
  if (!skel || prefersReducedMotion()) return;
  const exitClass = isGridSkeletonHost(skel)
    ? "kiosk-skeleton-host--exit"
    : skel.classList.contains("kiosk-skeleton-groups")
      ? "kiosk-skeleton-groups--exit"
      : skel.classList.contains("kiosk-skeleton-table")
        ? "kiosk-skeleton-table--exit"
        : "kiosk-skeleton-panel--exit";
  skel.classList.add(exitClass);
  await new Promise((resolve) => {
    let settled = false;
    const finish = () => {
      if (settled) return;
      settled = true;
      skel.removeEventListener("transitionend", onEnd);
      resolve();
    };
    const onEnd = (event) => {
      if (event.target === skel && event.propertyName === "opacity") finish();
    };
    skel.addEventListener("transitionend", onEnd);
    globalThis.setTimeout(finish, KIOSK_SKELETON_EXIT_MS + 40);
  });
}

function clearSkeletonHostAttrs(container) {
  if (!container) return;
  container.classList.remove("kiosk-skeleton-host--exit");
  container.removeAttribute("aria-busy");
  container.removeAttribute("aria-label");
}

export async function replaceKioskContent(container, html, options = {}) {
  if (!container) return;
  const { minMs = KIOSK_SKELETON_MIN_MS, startedAt = performance.now() } = options;
  const skel = findSkeletonRoot(container);
  if (skel) {
    await awaitKioskSkeletonMin(startedAt, minMs);
    await fadeOutSkeleton(skel);
  } else {
    await awaitKioskSkeletonMin(startedAt, minMs);
  }
  container.innerHTML = html;
  clearSkeletonHostAttrs(container);
}

export function clearStaleKioskSkeleton(container) {
  if (!container) return;
  if (findSkeletonRoot(container)) {
    container.innerHTML = "";
    clearSkeletonHostAttrs(container);
  }
}

export function mountDuplicatePanelSkeleton(recipeInfoEl, weightSectionEl) {
  const html = buildDuplicatePanelSkeletonHtml();
  const startedAt = performance.now();
  if (recipeInfoEl) {
    recipeInfoEl.style.display = "block";
    recipeInfoEl.innerHTML = html;
  }
  if (weightSectionEl) {
    weightSectionEl.classList.add("kiosk-skeleton-host");
    const host = weightSectionEl.querySelector(".weight-content");
    if (host) {
      host.dataset.kioskSkeletonBackup = host.innerHTML;
      host.innerHTML = `<div class="kiosk-skeleton-panel" aria-busy="true" aria-hidden="true">
        <div class="dashboard-skeleton-bar kiosk-skeleton-component-name"></div>
        <div class="dashboard-skeleton-bar kiosk-skeleton-weight-hero"></div>
      </div>`;
    }
  }
  return startedAt;
}

export function clearDuplicatePanelSkeleton(recipeInfoEl, weightSectionEl) {
  if (recipeInfoEl) {
    const skel = recipeInfoEl.querySelector(".kiosk-skeleton-panel");
    if (skel) {
      recipeInfoEl.style.display = "none";
      recipeInfoEl.innerHTML = `
        <h3>Рецепт: <span id="recipeName"></span></h3>
        <p>Компонент <span id="currentIndex">0</span> из <span id="totalComponents">0</span></p>`;
    }
  }
  if (weightSectionEl) {
    weightSectionEl.classList.remove("kiosk-skeleton-host");
    const host = weightSectionEl.querySelector(".weight-content");
    if (host?.dataset.kioskSkeletonBackup) {
      host.innerHTML = host.dataset.kioskSkeletonBackup;
      delete host.dataset.kioskSkeletonBackup;
    }
  }
}

const api = {
  buildGridSkeletonCards,
  buildDispenserGridSkeletonHtml,
  buildPeriodRecipeGridSkeletonHtml,
  buildUnloadingGroupsSkeletonHtml,
  buildDuplicatePanelSkeletonHtml,
  buildRecipeIngredientsSkeletonHtml,
  mountKioskSkeleton,
  replaceKioskContent,
  awaitKioskSkeletonMin,
  clearStaleKioskSkeleton,
  mountDuplicatePanelSkeleton,
  clearDuplicatePanelSkeleton,
};

if (typeof globalThis !== "undefined") {
  globalThis.WespKioskSkeleton = api;
}
