/**
 * toc.ts
 * Automatically generates a Table of Contents from h2/h3 headings
 * in the article body and highlights the active heading while scrolling.
 */

interface TocItem {
	id: string;
	text: string;
	level: 2 | 3;
}

export function initToc(): void {
	const tocList = document.getElementById( 'toc-list' );
	const article = document.querySelector<HTMLElement>( '.single-article .entry-content, .single-article .post-card__content' );

	if ( ! tocList || ! article ) return;

	const headings = Array.from(
		article.querySelectorAll<HTMLHeadingElement>( 'h2, h3' )
	);

	if ( headings.length < 2 ) {
		// Hide TOC widget when there aren't enough headings.
		const tocWidget = document.getElementById( 'toc' );
		if ( tocWidget ) tocWidget.hidden = true;
		return;
	}

	const items: TocItem[] = headings.map( ( heading ) => {
		if ( ! heading.id ) {
			// Generate a slug from heading text.
			heading.id = heading.textContent
				?.trim()
				.toLowerCase()
				.replace( /[^\w\u4e00-\u9fa5\s-]/g, '' )
				.replace( /\s+/g, '-' )
				.slice( 0, 60 ) ?? `heading-${ Math.random().toString( 36 ).slice( 2 ) }`;
		}

		return {
			id:    heading.id,
			text:  heading.textContent?.trim() ?? '',
			level: heading.tagName === 'H2' ? 2 : 3,
		};
	} );

	// Build ordered list HTML.
	const ol = document.createElement( 'ol' );
	let currentUl: HTMLUListElement | null = null;

	items.forEach( ( item ) => {
		const li   = document.createElement( 'li' );
		const link = document.createElement( 'a' );
		link.href      = `#${ item.id }`;
		link.textContent = item.text;
		link.className = `toc-link toc-level-${ item.level }`;

		link.addEventListener( 'click', ( e ) => {
			e.preventDefault();
			const target = document.getElementById( item.id );
			target?.scrollIntoView( { behavior: 'smooth', block: 'start' } );
		} );

		li.appendChild( link );

		if ( item.level === 2 ) {
			currentUl = null;
			ol.appendChild( li );
		} else {
			// Nest h3 items under the parent h2 list item.
			if ( ! currentUl ) {
				currentUl = document.createElement( 'ul' );
				currentUl.className = 'toc-sub-list';
				const lastH2 = ol.querySelector( 'li:last-child' );
				lastH2?.appendChild( currentUl );
			}
			currentUl.appendChild( li );
		}
	} );

	tocList.appendChild( ol );

	// Intersection Observer – highlight active heading.
	const links = tocList.querySelectorAll<HTMLAnchorElement>( '.toc-link' );

	const observer = new IntersectionObserver(
		( entries ) => {
			entries.forEach( ( entry ) => {
				const id   = entry.target.getAttribute( 'id' ) ?? '';
				const link = tocList.querySelector<HTMLAnchorElement>( `a[href="#${ id }"]` );
				if ( link ) {
					link.classList.toggle( 'toc-active', entry.isIntersecting );
				}
			} );
		},
		{
			rootMargin: '-80px 0px -60% 0px',
			threshold: 0,
		}
	);

	headings.forEach( ( h ) => observer.observe( h ) );
}
