import './style.css';

const pad = (value) => String(value).padStart(2, '0');

// Local storage is wrapped so blocked storage environments do not break the timer.
const safeStorage = {
  get(key) {
    try {
      return window.localStorage.getItem(key);
    } catch (error) {
      return null;
    }
  },
  set(key, value) {
    try {
      window.localStorage.setItem(key, value);
    } catch (error) {
      // Ignore storage write failures and continue with an in-memory countdown.
    }
  },
};

const getTarget = (root) => {
  const type = root.dataset.type || 'due';

  if (type === 'evergreen') {
    const hours = Number(root.dataset.hours || 24);
    const recurring = root.dataset.recurring === '1';
    const hostId = root.closest('.elementor-element')?.dataset.id || 'global';
    const key = 'calio_evergreen_' + hours + '_' + hostId;
    const saved = Number(safeStorage.get(key) || 0);
    const now = Date.now();
    const target = saved > now ? saved : now + hours * 3600000;
    safeStorage.set(key, String(target));
    return { target, key, recurring, hours };
  }

  const date = root.dataset.date ? new Date(root.dataset.date).getTime() : NaN;
  return { target: date, key: '', recurring: false, hours: 0 };
};

const initCountdown = (root, force = false) => {
  if (!(root instanceof HTMLElement) || !root.classList.contains('calio-countdown')) {
    return;
  }

  if (!force && root.dataset.calioCountdownInit === 'yes') {
    return;
  }

  if (force && root.__calioCountdownTimer) {
    window.clearInterval(root.__calioCountdownTimer);
    root.__calioCountdownTimer = null;
  }

  root.dataset.calioCountdownInit = 'yes';

  const cfg = getTarget(root);
  if (!cfg.target || Number.isNaN(cfg.target)) {
    return;
  }

  const expiredNode = root.nextElementSibling?.classList.contains('calio-countdown-expired')
    ? root.nextElementSibling
    : null;

  let didExpire = false;

  const expire = () => {
    if (didExpire) {
      return;
    }

    didExpire = true;

    // Redirect and hide behaviors are opt-in and come from sanitized widget settings.
    if (root.dataset.expire === 'redirect' && root.dataset.redirect) {
      window.location.href = root.dataset.redirect;
      return;
    }

    if (root.dataset.expire === 'hide') {
      root.style.display = 'none';
      return;
    }

    if (expiredNode) {
      root.style.display = 'none';
      expiredNode.style.display = 'grid';
    }
  };

  const update = () => {
    const now = Date.now();
    let diff = Math.max(cfg.target - now, 0);

    if (diff === 0 && cfg.recurring && cfg.key) {
      cfg.target = now + cfg.hours * 3600000;
      safeStorage.set(cfg.key, String(cfg.target));
      diff = cfg.target - now;
      didExpire = false;
    }

    const totalSeconds = Math.floor(diff / 1000);
    const map = {
      days: Math.floor(totalSeconds / 86400),
      hours: Math.floor((totalSeconds % 86400) / 3600),
      minutes: Math.floor((totalSeconds % 3600) / 60),
      seconds: totalSeconds % 60,
    };

    Object.keys(map).forEach((key) => {
      const node = root.querySelector('[data-unit="' + key + '"]');
      if (node) {
        node.textContent = pad(map[key]);
      }
    });

    if (diff === 0) {
      expire();
    }
  };

  update();
  const intervalId = window.setInterval(update, 1000);
  root.__calioCountdownTimer = intervalId;
};

const initCountdownScope = (scope = document, options = {}) => {
  const force = Boolean(options.force);
  const root = scope instanceof HTMLElement || scope instanceof Document ? scope : document;

  if (root instanceof HTMLElement && root.matches('.calio-countdown')) {
    initCountdown(root, force);
    return;
  }

  root.querySelectorAll('.calio-countdown').forEach((countdown) => initCountdown(countdown, force));
};

const safeInitDocument = (force = false) => {
  initCountdownScope(document, { force });
};

if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', () => {
    safeInitDocument();
  });
} else {
  safeInitDocument();
}

let calioCountdownHookBound = false;
const bindElementorCountdown = () => {
  if (calioCountdownHookBound) {
    return true;
  }

  if (!window.elementorFrontend?.hooks) {
    return false;
  }

  window.elementorFrontend.hooks.addAction('frontend/element_ready/calio-countdown.default', ($scope) => {
    const root = $scope?.[0] || document;
    initCountdownScope(root, { force: true });
  });

  calioCountdownHookBound = true;
  return true;
};

window.addEventListener('elementor/frontend/init', bindElementorCountdown);
if (!bindElementorCountdown()) {
  let attempts = 0;
  const timer = window.setInterval(() => {
    attempts += 1;
    if (bindElementorCountdown() || attempts >= 40) {
      window.clearInterval(timer);
    }
  }, 250);
}

if (window.MutationObserver) {
  const observer = new MutationObserver((mutations) => {
    mutations.forEach((mutation) => {
      mutation.addedNodes.forEach((node) => {
        if (!(node instanceof HTMLElement)) {
          return;
        }

        initCountdownScope(node, { force: true });
      });
    });
  });

  observer.observe(document.documentElement, {
    childList: true,
    subtree: true,
  });
}
