'use client';

import React, { useState, useEffect, useRef, useMemo } from 'react';
import { createPortal } from 'react-dom';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import { X } from 'lucide-react';
import clsx from 'clsx';
import { useT } from '../../../lib/i18n';
import { ActionIcon, Badge, Section } from '../../../components/ui';

interface GlossaryNode {
  uri?: string;
  node_uuid?: string;
  content_snippet?: string;
}

interface PopupPosition {
  x: number;
  y: number;
  isAbove: boolean;
  spanTop: number;
}

interface PopupState {
  keyword: string;
  nodes: GlossaryNode[];
  position: PopupPosition;
}

interface GlossaryPopupProps {
  keyword: string;
  nodes: GlossaryNode[];
  position: PopupPosition;
  onClose: () => void;
  onNavigate: (path: string, domain: string) => void;
}

interface GlossaryPopupRowProps {
  node: GlossaryNode;
  onNavigate: (path: string, domain: string) => void;
  onClose: () => void;
  t: (key: string) => string;
}

function GlossaryPopupRow({ node, onNavigate, onClose, t }: GlossaryPopupRowProps): React.JSX.Element {
  const isUnlinked = node.uri?.startsWith('unlinked://');

  return (
    <button
      type="button"
      disabled={isUnlinked}
      onClick={() => {
        if (isUnlinked) return;
        const match = node.uri?.match(/^([^:]+):\/\/(.*)$/);
        if (match) onNavigate(match[2], match[1]);
        onClose();
      }}
      className={clsx(
        'press w-full rounded-xl border border-transparent px-3 py-2.5 text-left transition-colors disabled:cursor-default disabled:opacity-60',
        !isUnlinked && 'hover:border-separator-thin hover:bg-fill-quaternary',
      )}
    >
      <div className="flex items-center gap-2">
        <code className={clsx(
          'flex-1 truncate font-mono text-[11.5px]',
          isUnlinked ? 'text-txt-tertiary' : 'text-txt-primary',
        )}>
          {node.uri}
        </code>
        {isUnlinked && (
          <Badge tone="red" size="xs">{t('Orphaned')}</Badge>
        )}
      </div>
      {node.content_snippet && (
        <p className="mt-1 line-clamp-2 text-[12px] leading-snug text-txt-secondary">{node.content_snippet}</p>
      )}
    </button>
  );
}

const GlossaryPopup = ({ keyword, nodes, position, onClose, onNavigate }: GlossaryPopupProps): React.JSX.Element => {
  const { t } = useT();
  const popupRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const handler = (e: MouseEvent) => {
      if (popupRef.current && !popupRef.current.contains(e.target as Node)) onClose();
    };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, [onClose]);

  return createPortal(
    <div
      ref={popupRef}
      className="animate-scale fixed z-[70] w-80"
      style={{
        left: Math.min(position.x, (typeof window !== 'undefined' ? window.innerWidth : 800) - 328),
        ...(position.isAbove
          ? { bottom: (typeof window !== 'undefined' ? window.innerHeight : 600) - position.spanTop + 8, maxHeight: position.spanTop - 24 }
          : { top: position.y + 8, maxHeight: (typeof window !== 'undefined' ? window.innerHeight : 600) - position.y - 24 }),
      }}
    >
      <Section
        compact
        className="overflow-hidden shadow-2xl shadow-black/40"
        title={(
          <span className="inline-flex min-w-0 items-center gap-2">
            <span className="text-[11px] font-medium uppercase tracking-[0.06em] text-txt-tertiary">{t('Entry')}</span>
            <span className="truncate text-[14px] font-semibold text-sys-yellow">{keyword}</span>
          </span>
        )}
        right={<ActionIcon icon={X} title={t('Close')} onClick={onClose} />}
        bodyClassName="max-h-[inherit] overflow-y-auto px-1.5 py-1.5"
      >
        <div className="space-y-1">
          {nodes.map((node, i) => (
            <GlossaryPopupRow
              key={node.uri || i}
              node={node}
              onNavigate={onNavigate}
              onClose={onClose}
              t={t}
            />
          ))}
        </div>
      </Section>
    </div>,
    document.body,
  );
};

interface GlossaryEntry {
  keyword?: string;
  nodes?: GlossaryNode[];
}

interface GlossaryHighlighterProps {
  content: string;
  glossary: GlossaryEntry[];
  currentNodeUuid: string;
  onNavigate: (path: string, domain?: string) => void;
}

const GlossaryHighlighter = ({ content, glossary, currentNodeUuid, onNavigate }: GlossaryHighlighterProps): React.JSX.Element => {
  const [popup, setPopup] = useState<PopupState | null>(null);
  const containerRef = useRef<HTMLDivElement>(null);

  useEffect(() => { setPopup(null); }, [content]);

  const filteredGlossary = useMemo((): GlossaryEntry[] => {
    if (!glossary) return [];
    return glossary.flatMap((entry) => {
      const nodes = entry.nodes?.filter((n) => n.node_uuid !== currentNodeUuid) || [];
      return nodes.length > 0 ? [{ ...entry, nodes }] : [];
    });
  }, [glossary, currentNodeUuid]);

  useEffect(() => {
    if (!filteredGlossary.length || !containerRef.current) return;
    const keywords = filteredGlossary.flatMap((entry) => entry.keyword ? [entry.keyword] : []);
    if (!keywords.length) return;

    const walker = document.createTreeWalker(containerRef.current, NodeFilter.SHOW_TEXT);
    const textNodes: Node[] = [];
    while (walker.nextNode()) textNodes.push(walker.currentNode);

    const keywordMap: Record<string, GlossaryEntry> = {};
    for (const entry of filteredGlossary) if (entry.keyword) keywordMap[entry.keyword] = entry;

    for (const textNode of textNodes) {
      const parentEl = textNode.parentElement;
      if (!parentEl) continue;
      if (parentEl.closest('code, pre, a, .glossary-keyword')) continue;

      const text = textNode.textContent;
      if (!text) continue;

      const matches: { start: number; end: number; keyword: string }[] = [];
      for (const kw of keywords) {
        let idx = text.indexOf(kw);
        while (idx !== -1) { matches.push({ start: idx, end: idx + kw.length, keyword: kw }); idx = text.indexOf(kw, idx + kw.length); }
      }
      if (!matches.length) continue;

      matches.sort((a, b) => a.start - b.start);
      const filtered: typeof matches = [];
      let lastEnd = -1;
      for (const match of matches) {
        if (match.start >= lastEnd) { filtered.push(match); lastEnd = match.end; }
      }

      const frag = document.createDocumentFragment();
      let pos = 0;
      for (const match of filtered) {
        if (match.start > pos) frag.appendChild(document.createTextNode(text.slice(pos, match.start)));
        const span = document.createElement('span');
        span.className = 'glossary-keyword';
        span.textContent = text.slice(match.start, match.end);
        span.dataset.keyword = match.keyword;
        frag.appendChild(span);
        pos = match.end;
      }
      if (pos < text.length) frag.appendChild(document.createTextNode(text.slice(pos)));
      textNode.parentNode?.replaceChild(frag, textNode);
    }

    const handleClick = (e: MouseEvent) => {
      const target = (e.target as Element).closest('.glossary-keyword') as HTMLElement | null;
      if (!target) return;
      const kw = target.dataset.keyword;
      if (!kw) return;
      const entry = keywordMap[kw];
      if (!entry) return;
      const rect = target.getBoundingClientRect();
      let x = rect.left;
      if (x + 288 > window.innerWidth - 16) x = window.innerWidth - 304;
      if (x < 16) x = 16;
      const estimatedHeight = 250;
      const isAbove = rect.bottom + estimatedHeight > window.innerHeight - 16 && rect.top > estimatedHeight + 16;
      setPopup({ keyword: kw, nodes: entry.nodes || [], position: { x, y: rect.bottom, isAbove, spanTop: rect.top } });
    };

    const container = containerRef.current;
    container.addEventListener('click', handleClick);
    return () => container?.removeEventListener('click', handleClick);
  }, [content, filteredGlossary]);

  return (
    <div ref={containerRef} className="relative">
      <ReactMarkdown remarkPlugins={[remarkGfm]}>{content}</ReactMarkdown>
      {popup && (
        <GlossaryPopup
          keyword={popup.keyword}
          nodes={popup.nodes}
          position={popup.position}
          onClose={() => setPopup(null)}
          onNavigate={onNavigate}
        />
      )}
    </div>
  );
};

export default GlossaryHighlighter;
