import React, { useState, useEffect, useRef, useMemo, useCallback } from "react";
import Prism from "prismjs";
import "prismjs/components/prism-markdown";
import "prismjs/components/prism-clike";
import "prismjs/components/prism-javascript";
import "prismjs/components/prism-typescript";
import "prismjs/components/prism-css";
import "prismjs/components/prism-json";
import { ChevronRight, ChevronDown, RefreshCw, AlertTriangle, Check, Info } from "lucide-react";
import { useSpellcheck } from "../hooks/useSpellcheck";
import { useEditorShortcuts } from "../hooks/useEditorShortcuts";
import { ParsedLine, parseLinesStructure } from "../utils/foldingUtils";

export type EditorThemeType = "slate" | "monokai" | "darcula" | "solarized-dark" | "solarized-light" | "terminal";

interface AestheticCodeEditorProps {
  value: string;
  onChange: (newValue: string) => void;
  theme: EditorThemeType;
  showStats?: boolean;
  onShowStats?: () => void;
  fontFamily?: "sans" | "serif" | "mono";
}

export const AestheticCodeEditor: React.FC<AestheticCodeEditorProps> = ({
  value,
  onChange,
  theme,
  showStats,
  onShowStats,
  fontFamily = "mono"
}) => {
  const [foldedHeadingIndices, setFoldedHeadingIndices] = useState<Record<number, boolean>>({});
  const [editorFontSize, setEditorFontSize] = useState<number>(12); 
  const [wordWrap, setWordWrap] = useState<boolean>(false); 
  const [activeLineIndex, setActiveLineIndex] = useState<number | null>(null);

  const textareaRef = useRef<HTMLTextAreaElement>(null);
  const highlightedRef = useRef<HTMLPreElement>(null);

  // Helper to determine active line based on cursor position
  const updateActiveLine = useCallback(() => {
    const textarea = textareaRef.current;
    if (!textarea) return;
    const selectionStart = textarea.selectionStart;
    const textBeforeCursor = textarea.value.substring(0, selectionStart);
    const lineIndex = textBeforeCursor.split(/\r?\n/).length - 1;
    setActiveLineIndex(lineIndex);
  }, []);

  // Generate unique ID for styles isolation
  const editorId = useMemo(() => Math.random().toString(36).substring(2, 9), []);

  // Sync scroll positions between Textarea and Highlight layer (pre)
  const handleScroll = (e: React.UIEvent<HTMLTextAreaElement>) => {
    const target = e.currentTarget;
    if (highlightedRef.current) {
      highlightedRef.current.scrollTop = target.scrollTop;
      highlightedRef.current.scrollLeft = target.scrollLeft;
    }
  };

  // Parsing full document into logical folders structure
  const originalLines = useMemo(() => value.split(/\r?\n/), [value]);

  const parsedLinesStructure = useMemo(() => {
    return parseLinesStructure(originalLines);
  }, [originalLines]);

  // Compute folded lines list
  const visibleLines = useMemo(() => {
    const visible: ParsedLine[] = [];
    const hiddenSet = new Set<number>();

    parsedLinesStructure.forEach((line) => {
      const parentIsFolded = foldedHeadingIndices[line.originalIndex];
      if (parentIsFolded && line.isFoldHeader) {
        const [start, end] = line.childrenLineRange;
        for (let j = start; j <= end; j++) {
          hiddenSet.add(j);
        }
      }
    });

    parsedLinesStructure.forEach((line) => {
      if (!hiddenSet.has(line.originalIndex)) {
        visible.push({
          ...line,
          isFolded: !!foldedHeadingIndices[line.originalIndex]
        });
      }
    });

    return visible;
  }, [parsedLinesStructure, foldedHeadingIndices]);

  // Generate text shown in editor
  const editorVisibleText = useMemo(() => {
    return visibleLines.map(v => v.text).join("\n");
  }, [visibleLines]);

  // Custom Hooks integration
  const {
    misspelledWords,
    ignoredWords,
    enableSpellcheck,
    setEnableSpellcheck,
    isSpellchecking,
    showSpellcheckDropdown,
    setShowSpellcheckDropdown,
    addToDictionary,
    clearAllExceptions
  } = useSpellcheck(editorVisibleText);

  // Unified visible text change processor to handle edits safely when sections are folded
  const processVisibleTextChange = useCallback((newVisibleText: string) => {
    const foldedCount = Object.keys(foldedHeadingIndices).length;
    if (foldedCount === 0) {
      onChange(newVisibleText);
      return;
    }

    const newVisibleLines = newVisibleText.split(/\r?\n/);
    const updatedOriginalLines = [...originalLines];

    // Find common prefix from top
    let prefixCount = 0;
    const maxPrefix = Math.min(newVisibleLines.length, visibleLines.length);
    while (prefixCount < maxPrefix && newVisibleLines[prefixCount] === visibleLines[prefixCount].text) {
      prefixCount++;
    }

    // Find common suffix from bottom, avoiding overlap with prefix
    let suffixCount = 0;
    const maxSuffix = Math.min(newVisibleLines.length - prefixCount, visibleLines.length - prefixCount);
    while (suffixCount < maxSuffix && 
           newVisibleLines[newVisibleLines.length - 1 - suffixCount] === visibleLines[visibleLines.length - 1 - suffixCount].text) {
      suffixCount++;
    }

    // Determine the range of visible lines that were modified
    const startVisibleIdx = prefixCount;
    const endVisibleIdx = visibleLines.length - 1 - suffixCount;

    // Determine the replacement lines in newVisibleLines
    const replacementLines = newVisibleLines.slice(prefixCount, newVisibleLines.length - suffixCount);

    let startOrigIdx = 0;
    let endOrigIdx = 0;
    let shift = 0;

    if (startVisibleIdx <= endVisibleIdx) {
      // Get the range of original lines that correspond to these modified visible lines
      startOrigIdx = visibleLines[startVisibleIdx].originalIndex;
      endOrigIdx = visibleLines[endVisibleIdx].originalIndex;
      const deleteCount = endOrigIdx - startOrigIdx + 1;
      const insertCount = replacementLines.length;
      shift = insertCount - deleteCount;

      // Replace the original range with replacementLines
      updatedOriginalLines.splice(startOrigIdx, deleteCount, ...replacementLines);
    } else {
      // No visible lines were modified directly, meaning it's a pure insertion at some boundary.
      // We can insert the replacement lines after the original index of the line before startVisibleIdx,
      // or at the beginning if startVisibleIdx is 0.
      let insertIdx = 0;
      if (startVisibleIdx > 0) {
        insertIdx = visibleLines[startVisibleIdx - 1].originalIndex + 1;
      } else if (visibleLines.length > 0) {
        insertIdx = visibleLines[0].originalIndex;
      }
      startOrigIdx = insertIdx;
      endOrigIdx = insertIdx - 1; // negative range to signify pure insertion
      shift = replacementLines.length;

      updatedOriginalLines.splice(insertIdx, 0, ...replacementLines);
    }

    // Shift foldedHeadingIndices accordingly
    const newFoldedHeadingIndices: Record<number, boolean> = {};
    Object.entries(foldedHeadingIndices).forEach(([keyStr, value]) => {
      const key = parseInt(keyStr, 10);
      if (key < startOrigIdx) {
        newFoldedHeadingIndices[key] = value;
      } else if (key > endOrigIdx) {
        newFoldedHeadingIndices[key + shift] = value;
      }
    });
    setFoldedHeadingIndices(newFoldedHeadingIndices);

    onChange(updatedOriginalLines.join("\n"));
  }, [originalLines, visibleLines, foldedHeadingIndices, onChange]);

  const { handleKeyDown } = useEditorShortcuts({
    textareaRef,
    onChange: processVisibleTextChange,
    updateActiveLine
  });

  // Handle updates directly in text-area
  const handleTextareaChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
    processVisibleTextChange(e.target.value);
  };

  // Standard Word & Character Counts calculated internally
  const internalWordCount = useMemo(() => {
    const clean = value.trim();
    if (clean === "") return 0;
    return clean.split(/\s+/).filter(Boolean).length;
  }, [value]);

  const internalCharCount = useMemo(() => {
    return value.length;
  }, [value]);

  // Method to render spellcheck decoration text overlay on top of standard line text
  const renderSpellcheckDecorations = (text: string) => {
    if (!text) return "\u200B";
    const parts = text.split(/(\b[A-Za-z']+\b)/);
    return parts.map((part, i) => {
      const isWord = /^[A-Za-z']+$/.test(part);
      const lowercaseWord = part.toLowerCase();
      // Only underline if spelling checker is active and word is unrecognized
      if (isWord && misspelledWords.has(lowercaseWord) && !ignoredWords.has(lowercaseWord)) {
        return (
          <span
            key={i}
            className="border-b-[1.5px] border-dotted border-red-500 text-transparent font-mono relative"
            title={`Spelling error: "${part}"`}
          >
            {part}
          </span>
        );
      }
      return <span key={i} className="text-transparent font-mono">{part}</span>;
    });
  };

  // Highlight markdown tokens line-by-line with Prism to avoid multi-line tag clipping
  const highlightedLines = useMemo(() => {
    return visibleLines.map((line) => {
      let html = "";
      try {
        html = Prism.highlight(line.text, Prism.languages.markdown || Prism.languages.markup, "markdown");
      } catch {
        html = line.text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
      }
      return html === "" ? "&#8203;" : html;
    });
  }, [visibleLines]);

  // Sync scroll positions
  useEffect(() => {
    if (textareaRef.current) {
      const top = textareaRef.current.scrollTop;
      const left = textareaRef.current.scrollLeft;
      if (highlightedRef.current) {
        highlightedRef.current.scrollTop = top;
        highlightedRef.current.scrollLeft = left;
      }
    }
  }, [editorVisibleText]);

  // Precise styles for themes to overwrite colorings & comments
  const getThemeStyles = () => {
    switch (theme) {
      case "monokai":
        return {
          bg: "bg-[#272822] text-[#F8F8F2]",
          border: "border-[#1E1F1C]",
          caret: "caret-[#F8F8F0]",
          gutterBg: "bg-[#1E1F1C] border-[#272822]/40",
          gutterText: "text-[#75715E]",
          lineNumHover: "hover:text-[#F8F8F2] hover:bg-[#272822]",
          scrollThumb: "rgba(255,255,255,0.08)",
          tagColor: "#F92672",
          commentColor: "#75715E",
          keywordColor: "#F92672",
          stringColor: "#E6DB74",
          numberColor: "#AE81FF",
          headingColor: "#A6E22E",
          lineHighlight: "bg-white/[0.04]",
          lineGutterHighlight: "bg-[#272822]"
        };
      case "darcula":
        return {
          bg: "bg-[#2B2B2B] text-[#A9B7C6]",
          border: "border-[#1E1E1E]",
          caret: "caret-[#BBBBBB]",
          gutterBg: "bg-[#232323] border-[#2B2B2B]/40",
          gutterText: "text-[#606366]",
          lineNumHover: "hover:text-[#A9B7C6] hover:bg-[#2B2B2B]",
          scrollThumb: "rgba(255,255,255,0.06)",
          tagColor: "#CC7832",
          commentColor: "#808080",
          keywordColor: "#CC7832",
          stringColor: "#6A8759",
          numberColor: "#6897BB",
          headingColor: "#FFC66D",
          lineHighlight: "bg-white/[0.03]",
          lineGutterHighlight: "bg-[#2e2e2e]"
        };
      case "solarized-dark":
        return {
          bg: "bg-[#002B36] text-[#839496]",
          border: "border-[#073642]",
          caret: "caret-[#93A1A1]",
          gutterBg: "bg-[#073642] border-[#002B36]/40",
          gutterText: "text-[#586E75]",
          lineNumHover: "hover:text-[#93A1A1] hover:bg-[#002B36]",
          scrollThumb: "rgba(255,255,255,0.05)",
          tagColor: "#268BD2",
          commentColor: "#586E75",
          keywordColor: "#B58900",
          stringColor: "#2AA198",
          numberColor: "#D33682",
          headingColor: "#268BD2",
          lineHighlight: "bg-[#073642]/60",
          lineGutterHighlight: "bg-[#0b3e4c]"
        };
      case "solarized-light":
        return {
          bg: "bg-[#FDF6E3] text-[#586E75]",
          border: "border-[#EEE8D5]",
          caret: "caret-[#073642]",
          gutterBg: "bg-[#EEE8D5] border-[#FDF6E3]/40",
          gutterText: "text-[#93A1A1]",
          lineNumHover: "hover:text-[#586E75] hover:bg-[#FDF6E3]",
          scrollThumb: "rgba(0,0,0,0.06)",
          tagColor: "#268BD2",
          commentColor: "#93A1A1",
          keywordColor: "#B58900",
          stringColor: "#2AA198",
          numberColor: "#D33682",
          headingColor: "#268BD2",
          lineHighlight: "bg-[#EEE8D5]/50",
          lineGutterHighlight: "bg-[#e2dac2]"
        };
      case "terminal":
        return {
          bg: "bg-[#04070A] text-[#10B981]",
          border: "border-emerald-500/10",
          caret: "caret-[#10B981]",
          gutterBg: "bg-[#020406] border-emerald-500/5",
          gutterText: "text-emerald-900/60",
          lineNumHover: "hover:text-[#10B981] hover:bg-emerald-950/20",
          scrollThumb: "rgba(16,185,129,0.1)",
          tagColor: "#059669",
          commentColor: "#065F46",
          keywordColor: "#34D399",
          stringColor: "#6EE7B7",
          numberColor: "#10B981",
          headingColor: "#34D399",
          lineHighlight: "bg-emerald-500/[0.04]",
          lineGutterHighlight: "bg-[#030609]"
        };
      default: // slate
        return {
          bg: "bg-[#0F1115] text-slate-200",
          border: "border-slate-850",
          caret: "caret-indigo-505",
          gutterBg: "bg-[#13161C] border-slate-900/10",
          gutterText: "text-slate-600",
          lineNumHover: "hover:text-white hover:bg-slate-800/45",
          scrollThumb: "rgba(255,255,255,0.08)",
          tagColor: "#C084FC",
          commentColor: "#64748B",
          keywordColor: "#F472B6",
          stringColor: "#38BDF8",
          numberColor: "#A78BFA",
          headingColor: "#818CF8",
          lineHighlight: "bg-indigo-500/[0.03]",
          lineGutterHighlight: "bg-[#181C24]"
        };
    }
  };

  const colors = getThemeStyles();

  const fontStyles = useMemo(() => {
    switch (fontFamily) {
      case "sans":
        return `system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif`;
      case "serif":
        return `Georgia, Cambria, "Times New Roman", Times, serif`;
      case "mono":
      default:
        return `"JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace`;
    }
  }, [fontFamily]);

  const inlineThemeCss = useMemo(() => {
    return `
      #editor-wrapper-${editorId} textarea,
      #editor-wrapper-${editorId} pre,
      #editor-wrapper-${editorId} code,
      #editor-wrapper-${editorId} .line-content {
        font-family: ${fontStyles} !important;
        font-size: ${editorFontSize}px !important;
        line-height: 24px !important;
        tab-size: 4 !important;
        -moz-tab-size: 4 !important;
        font-variant-ligatures: none !important;
        letter-spacing: normal !important;
        word-spacing: normal !important;
        text-transform: none !important;
      }

      #editor-wrapper-${editorId} pre .line-content {
        white-space: ${wordWrap ? "pre-wrap" : "pre"} !important;
        word-wrap: ${wordWrap ? "break-word" : "normal"} !important;
        overflow-wrap: ${wordWrap ? "break-word" : "normal"} !important;
        word-break: ${wordWrap ? "break-word" : "normal"} !important;
      }

      #editor-wrapper-${editorId} textarea {
        padding: 16px 16px 16px 16px !important;
        margin: 0 !important;
        border: none !important;
        outline: none !important;
        box-sizing: border-box !important;
        background: transparent !important;
        overflow-y: scroll !important;
        overflow-x: ${wordWrap ? "hidden" : "auto"} !important;
        resize: none !important;
        width: calc(100% - 52px) !important;
        height: 100% !important;
        left: 52px !important;
        white-space: ${wordWrap ? "pre-wrap" : "pre"} !important;
        word-wrap: ${wordWrap ? "break-word" : "normal"} !important;
        overflow-wrap: ${wordWrap ? "break-word" : "normal"} !important;
        word-break: ${wordWrap ? "break-word" : "normal"} !important;
      }

      #editor-wrapper-${editorId} pre {
        padding: 16px 0px 16px 0px !important;
        margin: 0 !important;
        border: none !important;
        outline: none !important;
        box-sizing: border-box !important;
        background: transparent !important;
        overflow-y: scroll !important;
        overflow-x: ${wordWrap ? "hidden" : "auto"} !important;
        width: 100% !important;
        height: 100% !important;
        scrollbar-width: thin !important;
        scrollbar-color: transparent transparent !important;
      }

      #editor-wrapper-${editorId} pre::-webkit-scrollbar {
        width: 8px !important;
        height: 8px !important;
      }

      #editor-wrapper-${editorId} pre::-webkit-scrollbar-thumb {
        background-color: transparent !important;
      }

      #editor-wrapper-${editorId} pre::-webkit-scrollbar-track {
        background-color: transparent !important;
      }

      #editor-wrapper-${editorId} textarea::-webkit-scrollbar {
        width: 8px !important;
        height: 8px !important;
      }
      #editor-wrapper-${editorId} textarea::-webkit-scrollbar-track {
        background: transparent !important;
      }
      #editor-wrapper-${editorId} textarea::-webkit-scrollbar-thumb {
        background: ${colors.scrollThumb} !important;
        border-radius: 4px !important;
      }
      #editor-wrapper-${editorId} textarea::-webkit-scrollbar-thumb:hover {
        background: rgba(255,255,255,0.15) !important;
      }

      #editor-wrapper-${editorId} .token.comment,
      #editor-wrapper-${editorId} .token.prolog,
      #editor-wrapper-${editorId} .token.doctype,
      #editor-wrapper-${editorId} .token.cdata {
        color: ${colors.commentColor} !important;
        font-style: italic !important;
      }
      #editor-wrapper-${editorId} .token.punctuation {
        color: inherit !important;
        opacity: 0.6 !important;
      }
      #editor-wrapper-${editorId} .token.property,
      #editor-wrapper-${editorId} .token.tag,
      #editor-wrapper-${editorId} .token.boolean,
      #editor-wrapper-${editorId} .token.number,
      #editor-wrapper-${editorId} .token.constant,
      #editor-wrapper-${editorId} .token.symbol,
      #editor-wrapper-${editorId} .token.deleted {
        color: ${colors.numberColor} !important;
      }
      #editor-wrapper-${editorId} .token.selector,
      #editor-wrapper-${editorId} .token.attr-name,
      #editor-wrapper-${editorId} .token.string,
      #editor-wrapper-${editorId} .token.char,
      #editor-wrapper-${editorId} .token.builtin,
      #editor-wrapper-${editorId} .token.inserted {
        color: ${colors.stringColor} !important;
      }
      #editor-wrapper-${editorId} .token.operator,
      #editor-wrapper-${editorId} .token.entity,
      #editor-wrapper-${editorId} .token.url {
        color: ${colors.tagColor} !important;
      }
      #editor-wrapper-${editorId} .token.atrule,
      #editor-wrapper-${editorId} .token.attr-value,
      #editor-wrapper-${editorId} .token.keyword {
        color: ${colors.keywordColor} !important;
        font-weight: bold !important;
      }
      #editor-wrapper-${editorId} .token.title,
      #editor-wrapper-${editorId} .token.important {
        color: ${colors.headingColor} !important;
        font-weight: bold !important;
      }
      #editor-wrapper-${editorId} .token.bold {
        font-weight: bold !important;
      }
      #editor-wrapper-${editorId} .token.italic {
        font-style: italic !important;
      }
    `;
  }, [colors, editorId, fontStyles, editorFontSize, wordWrap]);

  const handleIncreaseFontSize = () => {
    setEditorFontSize(prev => Math.min(prev + 1, 20));
  };
  const handleDecreaseFontSize = () => {
    setEditorFontSize(prev => Math.max(prev - 1, 9));
  };

  const currentLineHeight = "24px"; 
  const customEditorStyle = {
    fontFamily: fontStyles,
    fontSize: `${editorFontSize}px`,
    lineHeight: currentLineHeight,
  };

  return (
    <div 
      id={`editor-wrapper-${editorId}`}
      className={`flex-grow h-full w-full rounded-xl border ${colors.border} ${colors.bg} flex flex-col overflow-hidden shadow-lg relative`}
    >
      <style dangerouslySetInnerHTML={{ __html: inlineThemeCss }} />
      
      {/* Editor top status utility bar */}
      <div className="flex items-center justify-between px-4 py-2 bg-black/25 border-b border-white/[0.04] text-[10px] uppercase tracking-wider select-none shrink-0 font-sans gap-2 flex-wrap">
        <div className="flex items-center gap-2">
          <span className="inline-block h-2 w-2 rounded-full bg-indigo-505 animate-pulse" />
          <span className="font-mono text-slate-300 font-bold">{theme.replace("-", " ")} Workbench</span>
          <span className="text-slate-600 font-mono">•</span>
          <span className="text-slate-400 font-mono text-[9px] font-bold">
            {editorFontSize}px Mono
          </span>
        </div>
        
        {/* Code editor preferences header control tools */}
        <div className="flex items-center gap-2 flex-wrap">
          {/* Font Controls inline */}
          <div className="flex items-center bg-black/30 rounded border border-white/[0.05] p-0.5">
            <button
              type="button"
              onClick={handleDecreaseFontSize}
              className="px-1.5 py-0.5 text-slate-405 hover:text-white transition rounded cursor-pointer text-[10px]"
              title="Decrease Font Size"
            >
              A-
            </button>
            <div className="w-px h-3 bg-white/[0.08]" />
            <button
              type="button"
              onClick={handleIncreaseFontSize}
              className="px-1.5 py-0.5 text-slate-405 hover:text-white transition rounded cursor-pointer text-[10px]"
              title="Increase Font Size"
            >
              A+
            </button>
          </div>

          {/* Word wrap Toggle */}
          <button
            type="button"
            onClick={() => setWordWrap(!wordWrap)}
            className={`px-2 py-0.5 rounded text-[9px] font-bold tracking-tight transition cursor-pointer font-mono ${
              wordWrap 
                ? "bg-indigo-600/35 text-indigo-305 border border-indigo-500/20" 
                : "bg-black/20 text-slate-455 border border-white/[0.05] hover:text-white"
            }`}
            title="Toggle Soft Word Wrapping"
          >
            Wrap: {wordWrap ? "ON" : "OFF"}
          </button>

          {/* Spellcheck Toggle & Multi-action Dropdown with Error Badge */}
          <div className="relative flex items-center gap-1.5 z-30">
            <button
              type="button"
              onClick={() => setEnableSpellcheck(!enableSpellcheck)}
              className={`px-2 py-0.5 rounded text-[9px] font-bold tracking-tight transition cursor-pointer font-mono ${
                enableSpellcheck 
                  ? "bg-emerald-600/30 text-emerald-300 border border-emerald-500/20" 
                  : "bg-black/20 text-slate-455 border border-white/[0.05] hover:text-white"
              }`}
              title="Toggle Live spelling checking overlays"
            >
              Spell: {enableSpellcheck ? "ON" : "OFF"}
            </button>

            {enableSpellcheck && (
              <button
                type="button"
                onClick={() => setShowSpellcheckDropdown(!showSpellcheckDropdown)}
                className={`px-2 py-0.5 rounded text-[9px] font-bold tracking-tight transition cursor-pointer font-mono flex items-center gap-1 ${
                  misspelledWords.size > 0
                    ? "bg-red-500/15 border border-red-500/30 text-red-400 hover:bg-red-500/25 animate-pulse font-bold"
                    : "bg-black/20 border border-white/[0.05] text-slate-400 font-medium"
                }`}
                title="View spelling dictionary adjustments and unrecognized words"
              >
                <span>ABC</span>
                <span className="bg-black/40 px-1 rounded text-[8px]">{misspelledWords.size}</span>
              </button>
            )}

            {showSpellcheckDropdown && (
              <div className="absolute right-0 top-6 w-64 bg-[#0d1015] border border-slate-800 rounded-lg shadow-xl p-3 z-50 text-left normal-case font-sans">
                <div className="flex justify-between items-center pb-2 border-b border-white/[0.05] mb-2">
                  <span className="font-bold text-[9px] text-slate-300 uppercase tracking-widest flex items-center gap-1">
                    <AlertTriangle className="h-3 w-3 text-red-400 shrink-0" />
                    Spelling Errors ({misspelledWords.size})
                  </span>
                  <button 
                    type="button"
                    onClick={() => setShowSpellcheckDropdown(false)}
                    className="text-[10px] text-slate-500 hover:text-white transition cursor-pointer p-0.5"
                  >
                    ✕
                  </button>
                </div>
                {misspelledWords.size === 0 ? (
                  <div className="text-[10px] text-slate-400 py-3 text-center font-sans">
                    {isSpellchecking ? (
                      <span className="animate-pulse">Checking spelling... ⏳</span>
                    ) : (
                      <span>No spelling errors detected! ✨</span>
                    )}
                  </div>
                ) : (
                  <div className="max-h-48 overflow-y-auto space-y-1 pr-1 custom-scrollbar">
                    {Array.from(misspelledWords).map((word) => (
                      <div key={word} className="flex justify-between items-center bg-black/20 p-1 px-2 rounded text-[10px] border border-white/[0.02]">
                        <span className="font-mono text-red-400 font-medium underline decoration-wavy decoration-red-500/80">{word}</span>
                        <button
                          type="button"
                          onClick={() => addToDictionary(word)}
                          className="text-[8.5px] bg-indigo-650 hover:bg-indigo-600 text-white py-0.5 px-1.5 rounded font-sans cursor-pointer transition uppercase font-bold tracking-tight"
                          title="Add word to custom dictionary exceptions"
                        >
                          Learn
                        </button>
                      </div>
                    ))}
                  </div>
                )}
                <div className="mt-2 pt-2 border-t border-white/[0.05] text-[8px] text-slate-500 flex justify-between font-sans uppercase tracking-tight">
                  <span>Exceptions: {ignoredWords.size}</span>
                  {ignoredWords.size > 0 && (
                    <button
                      type="button"
                      onClick={clearAllExceptions}
                      className="text-indigo-400 hover:underline cursor-pointer font-bold"
                    >
                      Clear All
                    </button>
                  )}
                </div>
              </div>
            )}
          </div>

          {Object.keys(foldedHeadingIndices).length > 0 && (
            <button
              onClick={() => setFoldedHeadingIndices({})}
              className="px-2 py-0.5 bg-indigo-650 hover:bg-indigo-500 text-white rounded text-[9px] cursor-pointer transition flex items-center gap-1 font-mono font-bold"
            >
              Unfold All ({Object.keys(foldedHeadingIndices).length})
            </button>
          )}
        </div>
      </div>

      {/* Editor Body Area: Gutter on Left, Interactive inputs on Right */}
      <div className="flex-grow flex items-stretch overflow-hidden relative w-full h-full">
        
        {/* Container for Highlight and Textarea overlays */}
        <div className="flex-grow h-full w-full relative overflow-hidden">
          
          {/* Highlight Pre background container with embedded gutter layout */}
          <pre
            ref={highlightedRef}
            aria-hidden="true"
            className="absolute inset-x-0 top-0 bottom-0 m-0 w-full h-full text-left overflow-y-scroll pointer-events-none select-none z-0"
            style={{ 
              ...customEditorStyle,
              background: "transparent",
              scrollbarWidth: "none"
            }}
          >
            {visibleLines.map((line, idx) => {
              const html = highlightedLines[idx];
              const hasChildrenToFold = line.isFoldHeader;
              const originalIndex = line.originalIndex;
              const isActive = idx === activeLineIndex;

              return (
                <div 
                  key={originalIndex}
                  className={`flex items-stretch relative group/line w-full transition-colors duration-150 ${
                    isActive ? `${colors.lineHighlight || "bg-indigo-500/[0.03]"}` : ""
                  }`}
                  style={{ 
                    minHeight: currentLineHeight, 
                    lineHeight: currentLineHeight,
                  }}
                >
                  {/* Line Number Gutter Cell - stuck horizontally, scrolls vertically */}
                  <div 
                    className={`sticky left-0 w-[52px] shrink-0 select-none pointer-events-auto pr-2 border-r border-white/[0.04] z-20 flex items-stretch justify-end transition-colors duration-150 ${
                      isActive 
                        ? (colors.lineGutterHighlight || "bg-[#181C24]") 
                        : (colors.gutterBg || "bg-[#13161C]")
                    }`}
                  >
                    <div className="relative w-full h-full">
                      <div 
                        className="absolute top-0 left-0 right-0 flex items-center justify-between pl-1"
                        style={{ height: currentLineHeight }}
                      >
                        {/* Fold icon */}
                        {hasChildrenToFold ? (
                          <button
                            type="button"
                            onClick={() => {
                              setFoldedHeadingIndices(prev => ({
                                ...prev,
                                [originalIndex]: !prev[originalIndex]
                              }));
                            }}
                            className="text-indigo-405 hover:text-indigo-301 hover:scale-105 shrink-0 transition p-0.5 cursor-pointer flex items-center justify-center z-30 pointer-events-auto"
                            title={line.isFolded ? `Unfold segment lines [${line.childrenLineRange[0] + 1}-${line.childrenLineRange[1] + 1}]` : `Fold segment`}
                          >
                            {line.isFolded ? (
                              <ChevronRight className="h-3 w-3" />
                            ) : (
                              <ChevronDown className="h-3 w-3" />
                            )}
                          </button>
                        ) : (
                          line.blockType === "paragraph" ? (
                            <button
                              type="button"
                              onClick={() => {
                                setFoldedHeadingIndices(prev => {
                                  const updated = { ...prev };
                                  if (updated[originalIndex]) {
                                    delete updated[originalIndex];
                                  } else {
                                    updated[originalIndex] = true;
                                  }
                                  return updated;
                                });
                              }}
                              className="text-[8px] text-slate-500/30 hover:text-indigo-400 hover:scale-125 cursor-pointer transition opacity-0 group-hover/line:opacity-100 p-0.5 shrink-0 flex items-center justify-center z-30 pointer-events-auto"
                              title="Fold paragraph body"
                            >
                              ▪
                            </button>
                          ) : (
                            <div className="w-3.5 h-3.5" />
                          )
                        )}

                        {/* Line number label */}
                        <span className={`text-[10px] select-none transition ${line.isFolded ? "text-indigo-400 font-bold underline" : (isActive ? "text-white font-bold" : colors.gutterText)} px-1 rounded`}>
                          {originalIndex + 1}
                        </span>
                      </div>
                    </div>
                  </div>

                  {/* Highlight text code block content */}
                  <div 
                    className="flex-1 min-w-0 pl-4 pr-4 line-content break-words relative z-0"
                    style={{
                      fontFamily: fontStyles,
                      fontSize: `${editorFontSize}px`,
                      lineHeight: currentLineHeight,
                    }}
                  >
                    <span 
                      dangerouslySetInnerHTML={{ __html: html }}
                      className="block w-full h-full"
                    />

                    {/* Foreground Spellcheck Red Underlines overlay */}
                    {enableSpellcheck && (
                      <div 
                        className="absolute inset-y-0 left-4 right-4 pointer-events-none select-none z-10 font-mono"
                        style={{
                          fontSize: `${editorFontSize}px`,
                          lineHeight: currentLineHeight,
                          whiteSpace: wordWrap ? "pre-wrap" : "pre",
                          wordWrap: wordWrap ? "break-word" : "normal",
                          overflowWrap: wordWrap ? "break-word" : "normal",
                          wordBreak: wordWrap ? "break-word" : "normal",
                        }}
                      >
                        {renderSpellcheckDecorations(line.text)}
                      </div>
                    )}
                  </div>
                </div>
              );
            })}
          </pre>

          {/* Transparent Input Textarea precisely offset by 52px */}
          <textarea
            ref={textareaRef}
            value={editorVisibleText}
            onChange={(e) => {
              handleTextareaChange(e);
              setTimeout(updateActiveLine, 0);
            }}
            onKeyDown={handleKeyDown}
            onScroll={handleScroll}
            onSelect={updateActiveLine}
            onFocus={updateActiveLine}
            onBlur={() => setActiveLineIndex(null)}
            wrap={wordWrap ? "soft" : "off"}
            placeholder="Type your markdown file code contents. Use # for foldable headings level segmenting..."
            className="absolute top-0 bottom-0 m-0 bg-transparent text-transparent caret-current focus:outline-none focus:ring-0 resize-none z-10 overflow-y-scroll border-none selection:bg-indigo-500/30 selection:text-white/90"
            style={{ 
              ...customEditorStyle,
              outline: "none",
              border: "none",
              left: "52px",
              width: "calc(100% - 52px)",
              paddingTop: "16px",
              paddingBottom: "16px",
              paddingLeft: "16px",
              paddingRight: "16px"
            }}
            spellCheck="false"
          />

        </div>
      </div>

      {/* FOOTER: Word Count, Char Count */}
      <div className="flex select-none items-center justify-between flex-wrap gap-2 px-4 py-1.5 bg-black/15 border-t border-white/[0.04] text-[9px] text-slate-500 font-sans">
        <div className="flex items-center gap-3">
          <span className="flex items-center gap-1">
            <Check className="h-3 w-3 text-indigo-405 shrink-0" />
            <span className="text-slate-400 font-mono font-medium">{internalWordCount}</span> words
          </span>
          <span className="flex items-center gap-1">
            <Info className="h-3 w-3 text-slate-500 shrink-0" />
            <span className="text-slate-400 font-mono font-medium">{internalCharCount}</span> characters
          </span>
          <span className="text-slate-700 font-mono">•</span>
          <span className="text-slate-400 font-mono">
            {originalLines.length} lines total
          </span>
        </div>
        
        <div className="flex items-center gap-2">
          {onShowStats && (
            <button
              type="button"
              onClick={onShowStats}
              title="Show comprehensive copywriting metrics popover"
              className={`text-[8.5px] px-2 py-0.5 rounded transition cursor-pointer font-mono font-medium border flex items-center gap-1 ${
                showStats
                  ? "bg-blue-600/30 border-blue-500 text-blue-300 font-bold"
                  : "bg-slate-900/60 border-slate-855 text-slate-400 hover:text-white hover:border-slate-700"
              }`}
            >
              <Info className="h-2.5 w-2.5" />
              <span>{showStats ? "Hide Stats" : "Details"}</span>
            </button>
          )}
          <span className="text-[8px] bg-slate-900 px-1.5 py-0.5 rounded border border-slate-800 text-slate-500 font-bold font-mono">
            ESC folds
          </span>
          {Object.keys(foldedHeadingIndices).length > 0 && (
            <span className="text-indigo-400 font-bold animate-pulse font-mono text-[8px] uppercase">
              {Object.keys(foldedHeadingIndices).length} segments folded
            </span>
          )}
        </div>
      </div>
    </div>
  );
};
