import { useCallback, useEffect, useRef } from 'react';

// Unique ID for the aria-live notification area element.
const notificationAreaId = 'loader-notification-area';
// Custom attribute to track active spinners
const activeSpinnersAttr = 'data-active-spinners';

// Generates a random unique ID for each spinner instance.
function generateUniqueId() {
  return `spinner-${Math.random().toString(36).substring(2, 9)}`;
}

// Finds or creates the notification area element in the DOM.
const getOrCreateNotificationArea = (): HTMLElement => {
  let element = document.getElementById(notificationAreaId);

  // Create and append it to the DOM.
  if (!element) {
    element = document.createElement('div');
    element.id = notificationAreaId;
    element.setAttribute('role', 'status');
    element.setAttribute('aria-live', 'polite');
    element.className = 'ds-visually-hidden';
    document.body.appendChild(element);
  }

  return element;
};

export const useNotificationArea = (
  loadingText = 'Γίνεται φόρτωση...',
  finishedText = 'Η φόρτωση ολοκληρώθηκε.'
) => {
  // Unique ID for this spinner.
  const spinnerId = useRef(generateUniqueId());
  // Reference to the notification area DOM element.
  const notificationRef = useRef<HTMLElement | null>(null);

  // Returns an array of active spinner IDs.
  const getActiveIds = useCallback(() => {
    const current = notificationRef.current;
    const value = current?.getAttribute(activeSpinnersAttr) || '';
    return value.split(',').filter(Boolean);
  }, [notificationRef]);

  // Adds this spinner's ID to the active list.
  const setActiveSpinnerId = useCallback(() => {
    const current = notificationRef.current;
    if (current) {
      const ids = new Set(getActiveIds());
      ids.add(spinnerId.current);
      current.setAttribute(activeSpinnersAttr, Array.from(ids).join(','));
    }
  }, [notificationRef, getActiveIds, spinnerId]);

  // Removes this spinner's ID from the active list.
  const unsetActiveSpinnerId = useCallback(() => {
    const current = notificationRef.current;
    if (current) {
      const ids = getActiveIds().filter((id) => id !== spinnerId.current);
      current.setAttribute(activeSpinnersAttr, ids.join(','));
    }
  }, [notificationRef, getActiveIds, spinnerId]);

  // Updates the text content of the aria-live region.
  const setTextContent = (text: string) => {
    if (notificationRef.current) {
      notificationRef.current.textContent = text;
    }
  };

  useEffect(() => {
    if (typeof document === 'undefined') return;

    // Set up notification area and mark this spinner as active.
    notificationRef.current = getOrCreateNotificationArea();
    setActiveSpinnerId();
    setTextContent(loadingText);

    // Cleanup when component unmounts.
    return () => {
      unsetActiveSpinnerId();

      // If no active spinners remain, announce "finished" and clear the text.
      if (getActiveIds().length === 0) {
        setTextContent(finishedText);

        // Give screen readers a chance to announce "finished" before clearing.
        setTimeout(() => {
          const el = notificationRef.current;
          if (el && getActiveIds().length === 0) {
            el.removeAttribute(activeSpinnersAttr);
            el.textContent = '';
          }
        }, 1000);
      }
    };
  }, [
    loadingText,
    finishedText,
    setActiveSpinnerId,
    unsetActiveSpinnerId,
    getActiveIds,
  ]);
};
