"use client";

import { IconChevronDown, IconList } from "@tabler/icons-react";
import { useLocale } from "next-intl";
import { useCallback, useEffect, useRef, useState } from "react";
import type { TocItem } from "@/lib/extract-headings";

const tocLabels = {
  fr: { title: "Sur cette page", toc: "Table des matières" },
  en: { title: "On this page", toc: "Table of contents" },
} as const;

function useActiveHeading(headings: TocItem[]) {
  const [activeId, setActiveId] = useState<string>("");

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

    const observer = new IntersectionObserver(
      (entries) => {
        for (const entry of entries) {
          if (entry.isIntersecting) {
            setActiveId(entry.target.id);
          }
        }
      },
      { rootMargin: "-80px 0px -70% 0px" }
    );

    for (const heading of headings) {
      const el = document.getElementById(heading.id);
      if (el) {
        observer.observe(el);
      }
    }

    return () => observer.disconnect();
  }, [headings]);

  return activeId;
}

function TocList({
  headings,
  activeId,
  onLinkClick,
  isVisible = true,
}: {
  headings: TocItem[];
  activeId: string;
  onLinkClick?: () => void;
  isVisible?: boolean;
}) {
  const listRef = useRef<HTMLOListElement>(null);

  // Auto-scroll active item into view — only when TOC is visible (not collapsed on mobile)
  useEffect(() => {
    if (!(activeId && listRef.current && isVisible)) {
      return;
    }
    const activeEl = listRef.current.querySelector(
      `[data-toc-id="${activeId}"]`
    );
    if (activeEl) {
      activeEl.scrollIntoView({ block: "nearest", behavior: "smooth" });
    }
  }, [activeId, isVisible]);

  return (
    <ol className="relative space-y-0.5" ref={listRef}>
      {headings.map((heading) => {
        const isActive = activeId === heading.id;
        return (
          <li
            className="relative"
            data-toc-id={heading.id}
            key={heading.id}
            style={{ paddingLeft: heading.level === 3 ? 16 : 0 }}
          >
            <span
              className={`absolute top-0 -left-3 h-full w-0.5 rounded-full bg-[#fd105e] transition-opacity duration-200 ${
                isActive ? "opacity-100" : "opacity-0"
              }`}
            />
            <a
              className={`block rounded px-3 py-1.5 text-[13px] leading-snug transition-colors duration-150 ${
                isActive
                  ? "font-medium text-white"
                  : "text-neutral-500 hover:text-neutral-300"
              }`}
              href={`#${heading.id}`}
              onClick={onLinkClick}
            >
              {heading.text}
            </a>
          </li>
        );
      })}
    </ol>
  );
}

/** Sticky sidebar TOC for desktop (xl+) */
export function TableOfContentsSidebar({ headings }: { headings: TocItem[] }) {
  const activeId = useActiveHeading(headings);
  const scrollRef = useRef<HTMLDivElement>(null);
  const locale = useLocale() as keyof typeof tocLabels;
  const labels = tocLabels[locale] ?? tocLabels.en;

  if (headings.length < 3) {
    return null;
  }

  return (
    <nav aria-label={labels.toc} className="w-56">
      <p className="mb-3 flex items-center gap-2 font-semibold text-neutral-500 text-xs uppercase tracking-wider">
        <IconList size={14} stroke={2} />
        {labels.title}
      </p>
      <div
        className="scrollbar-thin scrollbar-track-transparent scrollbar-thumb-white/10 max-h-[calc(100vh-10rem)] overflow-y-auto overscroll-contain"
        ref={scrollRef}
      >
        <TocList activeId={activeId} headings={headings} />
      </div>
    </nav>
  );
}

/** Collapsible inline TOC for mobile */
export function TableOfContentsInline({ headings }: { headings: TocItem[] }) {
  const activeId = useActiveHeading(headings);
  const [isExpanded, setIsExpanded] = useState(false);
  const scrollRef = useRef<HTMLDivElement>(null);
  const locale = useLocale() as keyof typeof tocLabels;
  const labels = tocLabels[locale] ?? tocLabels.en;

  const handleLinkClick = useCallback(() => setIsExpanded(false), []);

  if (headings.length < 3) {
    return null;
  }

  return (
    <nav
      aria-label={labels.toc}
      className="mb-10 rounded-2xl border border-white/10 bg-white/5 p-5"
    >
      <button
        aria-expanded={isExpanded}
        className="flex w-full cursor-pointer items-center justify-between font-semibold text-neutral-300 text-sm transition-colors hover:text-white"
        onClick={() => setIsExpanded((prev) => !prev)}
        type="button"
      >
        <span className="flex items-center gap-2">
          <IconList size={18} stroke={1.5} />
          <span>{labels.toc}</span>
          <span className="font-normal text-neutral-500 text-xs">
            ({headings.length})
          </span>
        </span>
        <IconChevronDown
          className={`transition-transform duration-200 ${isExpanded ? "rotate-180" : ""}`}
          size={16}
          stroke={2}
        />
      </button>
      <div
        className={`transition-all duration-300 ease-in-out ${
          isExpanded
            ? "mt-4 max-h-[60vh] overflow-y-auto overscroll-contain opacity-100"
            : "max-h-0 overflow-hidden opacity-0"
        }`}
        ref={scrollRef}
      >
        <TocList
          activeId={activeId}
          headings={headings}
          isVisible={isExpanded}
          onLinkClick={handleLinkClick}
        />
      </div>
    </nav>
  );
}

/** Backwards-compatible export */
function _TableOfContents({ headings }: { headings: TocItem[] }) {
  return <TableOfContentsInline headings={headings} />;
}
