import { createSignal, onMount, createEffect, For, Show } from 'solid-js';
import type { Component } from 'solid-js';

interface Heading {
  id: string;
  text: string;
}

const slugify = (text: string) => {
  return text
    .toLowerCase()
    .replace(/[^\w\s-]/g, '')
    .replace(/\s+/g, '-')
    .replace(/--+/g, '-');
};

const throttle = (fn: () => void, delay: number) => {
  let timeoutId: number | null = null;
  return () => {
    if (timeoutId) return;
    timeoutId = window.setTimeout(() => {
      fn();
      timeoutId = null;
    }, delay);
  };
};

const TableOfContents: Component = () => {
  const [headings, setHeadings] = createSignal<Heading[]>([]);
  const [activeId, setActiveId] = createSignal('');
  let headingElements: HTMLHeadingElement[] = [];

  onMount(() => {
    setTimeout(() => {
      const elements = Array.from(
        document.querySelectorAll('article h2'),
      ) as HTMLHeadingElement[];
      const extractedHeadings = elements.map((el, index) => {
        const originalText = el.innerText.replace(/^\d+\.\s*/, '');
        const id = `${slugify(originalText)}-${index}`;
        const numberedText = `${index + 1}. ${originalText}`;
        el.id = id;
        el.innerHTML = numberedText;
        return { id, text: numberedText };
      });
      headingElements = elements;
      setHeadings(extractedHeadings);
    }, 100);
  });

  createEffect(() => {
    if (headings().length === 0) return;

    const handler = () => {
      const headerOffset = document.getElementById('header')?.offsetHeight || 90;
      const topOffset = headerOffset + 160;

      // Batch the DOM reads to avoid layout thrashing
      const headingTops = headingElements.map(h => h.getBoundingClientRect().top);

      let currentActiveId = '';
      // Iterate over the stored values, not the DOM elements
      for (let i = 0; i < headingTops.length; i++) {
        const top = headingTops[i];
        if (top <= topOffset) {
          currentActiveId = headingElements[i].id;
        } else {
          break;
        }
      }
      setActiveId(currentActiveId);
    };

    const throttledHandler = throttle(handler, 100);
    window.addEventListener('scroll', throttledHandler, { passive: true });
    handler(); // run once on creation

  });

  const handleLinkClick = (
    e: MouseEvent,
    id: string,
  ) => {
    e.preventDefault();
    const element = document.getElementById(id);
    const header = document.getElementById('header');
    if (element && header) {
      const headerOffset = header.offsetHeight;
      const elementPosition = element.getBoundingClientRect().top;
      const offsetPosition =
        elementPosition + window.pageYOffset - headerOffset - 20;
      window.scrollTo({ top: offsetPosition, behavior: 'smooth' });
    }
  };

  return (
    <Show when={headings().length > 0}>
      <nav class="mb-12 block w-full rounded-lg border border-neutral-700 bg-neutral-900/80 p-4 backdrop-blur-sm lg:fixed lg:right-10 lg:top-1/2 lg:w-64 lg:-translate-y-1/2 lg:mb-0">
        <h2 class="mb-4 text-center text-xl font-bold text-white">Содержание</h2>
        <ul>
          <For each={headings()}>
            {(heading) => (
              <li class="my-1">
                <a
                  href={`#${heading.id}`}
                  onClick={(e) => handleLinkClick(e, heading.id)}
                  classList={{
                    'block text-sm transition-colors duration-200': true,
                    'font-semibold text-white': activeId() === heading.id,
                    'text-neutral-400 hover:text-white': activeId() !== heading.id,
                  }}
                >
                  {heading.text}
                </a>
              </li>
            )}
          </For>
        </ul>
      </nav>
    </Show>
  );
};

export default TableOfContents;