import { useState, useRef, useCallback, useMemo, useEffect } from 'react';
import {
  Segmented,
  Tree,
  Input,
  Button,
  Spin,
  Modal,
  Typography,
  Dropdown,
  List,
  theme,
  Result,
} from 'antd';
import type { TreeDataNode, MenuProps } from 'antd';
import {
  FileAddOutlined,
  FolderAddOutlined,
  DeleteOutlined,
  EditOutlined,
  SearchOutlined,
  ReloadOutlined,
  FileMarkdownOutlined,
  UploadOutlined,
  EyeOutlined,
  CodeOutlined,
  FolderOutlined,
  BuildOutlined,
  EllipsisOutlined,
  PlusOutlined,
  CloseOutlined,
  FileOutlined,
  FolderOpenOutlined,
} from '@ant-design/icons';
import type { UseDocsEditorReturn } from '@/hooks/useDocsEditor';
import { isImageFile } from '@/hooks/useDocsEditor';
import { MobileFormattingToolbar } from './MobileFormattingToolbar';
import type { InsertRequestType } from './MobileFormattingToolbar';
import { useMkDocsBuild } from '@/hooks/useMkDocsBuild';
import { VideoPickerModal } from '@/components/media/VideoPickerModal';
import type { Video as PickerVideo } from '@/components/media/VideoPickerModal';
import { PhotoPickerModal } from '@/components/media/PhotoPickerModal';
import type { Photo as PickerPhoto } from '@/components/media/PhotoPickerModal';
import { PhotoInsertModal } from '@/components/media/PhotoInsertModal';
import type { PhotoInsertResult } from '@/components/media/PhotoInsertModal';
import { generateVideoCardHtml } from '@/utils/videoCardHtml';
import { generatePhotoCardHtml } from '@/utils/photoCardHtml';
import { DonateInsertModal } from '@/components/payments/DonateInsertModal';
import type { DonateInsertResult } from '@/components/payments/DonateInsertModal';
import { ProductInsertModal } from '@/components/payments/ProductInsertModal';
import type { ProductInsertResult } from '@/components/payments/ProductInsertModal';
import { AdPickerModal } from '@/components/media/AdPickerModal';
import type { AdInsertResult } from '@/components/media/AdPickerModal';
import { PollInsertModal } from '@/components/scheduling/PollInsertModal';
import { WikiLinkPickerModal } from '@/components/docs/WikiLinkPickerModal';
import { MoveToModal } from '@/components/docs/MoveToModal';
import { useDocsCollaboration } from '@/hooks/useDocsCollaboration';
import { CollaboratorAvatars } from '@/components/docs/CollaboratorAvatars';
import { YTextareaBinding } from '@/lib/y-textarea';

type MobileTab = 'files' | 'editor' | 'preview';

interface MobileDocsEditorProps {
  editor: UseDocsEditorReturn;
  collabEnabled?: boolean;
}

// Flatten file tree into a searchable list of file paths
interface FlatFile { path: string; name: string; }
function flattenFiles(nodes: import('@/types/api').FileNode[]): FlatFile[] {
  const out: FlatFile[] = [];
  for (const n of nodes) {
    if (n.isDirectory) {
      if (n.children) out.push(...flattenFiles(n.children));
    } else {
      out.push({ path: n.path, name: n.name });
    }
  }
  return out;
}

function fileNodeToTreeData(nodes: import('@/types/api').FileNode[]): TreeDataNode[] {
  return nodes.map((node) => {
    const displayName = !node.isDirectory && node.name.endsWith('.md')
      ? node.name.slice(0, -3)
      : node.name;
    const treeNode: TreeDataNode = {
      key: node.path,
      title: displayName,
      isLeaf: !node.isDirectory,
    };
    if (node.isDirectory && node.children) {
      treeNode.children = fileNodeToTreeData(node.children);
    }
    return treeNode;
  });
}

const LINE_HEIGHT = 20;
const MONO_FONT = 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace';
const FONT_SIZE = 13;

function LineNumberedEditor({
  textareaRef,
  value,
  onChange,
  token,
}: {
  textareaRef: React.RefObject<HTMLTextAreaElement | null>;
  value: string;
  onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
  token: ReturnType<typeof theme.useToken>['token'];
}) {
  const gutterRef = useRef<HTMLDivElement>(null);
  const mirrorRef = useRef<HTMLDivElement>(null);
  const wrapperRef = useRef<HTMLDivElement>(null);
  const [lineHeights, setLineHeights] = useState<number[]>([]);
  const lines = useMemo(() => value.split('\n'), [value]);

  // Measure actual rendered height of each line using a hidden mirror div
  const measureLines = useCallback(() => {
    const mirror = mirrorRef.current;
    const wrapper = wrapperRef.current;
    if (!mirror || !wrapper) return;

    // Mirror width must match textarea content area (wrapper - gutter - textarea padding)
    const contentWidth = wrapper.clientWidth - 36 - 12;
    if (contentWidth <= 0) return;
    mirror.style.width = `${contentWidth}px`;

    // Render all lines as child divs, measure in a single reflow
    const fragment = document.createDocumentFragment();
    for (const line of lines) {
      const div = document.createElement('div');
      div.textContent = line || '\u00a0';
      fragment.appendChild(div);
    }
    mirror.textContent = '';
    mirror.appendChild(fragment);

    const heights: number[] = [];
    const children = mirror.children;
    for (let i = 0; i < children.length; i++) {
      heights.push((children[i] as HTMLElement).offsetHeight);
    }
    setLineHeights(heights);
  }, [lines]);

  // Remeasure on content change and container resize
  useEffect(() => {
    measureLines();
    const wrapper = wrapperRef.current;
    if (!wrapper) return;
    const observer = new ResizeObserver(measureLines);
    observer.observe(wrapper);
    return () => observer.disconnect();
  }, [measureLines]);

  // Sync gutter scroll with textarea scroll
  const handleScroll = useCallback(() => {
    if (gutterRef.current && textareaRef.current) {
      gutterRef.current.scrollTop = textareaRef.current.scrollTop;
    }
  }, [textareaRef]);

  // Attach scroll listener
  useEffect(() => {
    const ta = textareaRef.current;
    if (!ta) return;
    ta.addEventListener('scroll', handleScroll);
    return () => ta.removeEventListener('scroll', handleScroll);
  }, [textareaRef, handleScroll]);

  return (
    <div ref={wrapperRef} style={{ flex: 1, display: 'flex', minHeight: 0, overflow: 'hidden', position: 'relative' }}>
      {/* Hidden mirror div — same font/wrapping as textarea, used to measure line heights */}
      <div
        ref={mirrorRef}
        aria-hidden="true"
        style={{
          position: 'absolute',
          visibility: 'hidden',
          height: 'auto',
          whiteSpace: 'pre-wrap',
          wordBreak: 'break-all',
          fontFamily: MONO_FONT,
          fontSize: FONT_SIZE,
          lineHeight: `${LINE_HEIGHT}px`,
        }}
      />
      {/* Line number gutter */}
      <div
        ref={gutterRef}
        style={{
          width: 36,
          flexShrink: 0,
          overflow: 'hidden',
          paddingTop: 4,
          background: token.colorBgLayout,
          borderRight: `1px solid ${token.colorBorderSecondary}`,
          userSelect: 'none',
          fontFamily: MONO_FONT,
          fontSize: FONT_SIZE - 2,
          lineHeight: `${LINE_HEIGHT}px`,
          color: token.colorTextQuaternary,
          textAlign: 'right',
          paddingRight: 6,
        }}
      >
        {(lineHeights.length > 0 ? lineHeights : lines.map(() => LINE_HEIGHT)).map((h, i) => (
          <div key={i + 1} style={{ height: h }}>{i + 1}</div>
        ))}
      </div>
      {/* Textarea */}
      <textarea
        ref={textareaRef}
        value={value}
        onChange={onChange}
        spellCheck={false}
        style={{
          flex: 1,
          minHeight: 0,
          height: '100%',
          border: 'none',
          outline: 'none',
          resize: 'none',
          padding: '4px 6px',
          margin: 0,
          fontFamily: MONO_FONT,
          fontSize: FONT_SIZE,
          lineHeight: `${LINE_HEIGHT}px`,
          background: 'transparent',
          color: token.colorText,
          boxSizing: 'border-box',
          overflow: 'auto',
          whiteSpace: 'pre-wrap',
          wordBreak: 'break-all',
          overflowX: 'hidden',
          WebkitTextSizeAdjust: 'none',
        }}
      />
    </div>
  );
}

export function MobileDocsEditor({ editor, collabEnabled = false }: MobileDocsEditorProps) {
  const { token } = theme.useToken();
  const { building, confirmAndBuild, isSuperAdmin } = useMkDocsBuild();
  const [activeTab, setActiveTab] = useState<MobileTab>('files');
  const [searchOpen, setSearchOpen] = useState(false);
  const textareaRef = useRef<HTMLTextAreaElement>(null);
  const yBindingRef = useRef<YTextareaBinding | null>(null);

  // Insert modal state
  const [videoPickerOpen, setVideoPickerOpen] = useState(false);
  const [photoInsertOpen, setPhotoInsertOpen] = useState(false);
  const [photoPickerOpen, setPhotoPickerOpen] = useState(false);
  const [pendingPhotoVariant, setPendingPhotoVariant] = useState<PhotoInsertResult | null>(null);
  const [donateInsertOpen, setDonateInsertOpen] = useState(false);
  const [productInsertOpen, setProductInsertOpen] = useState(false);
  const [adPickerOpen, setAdPickerOpen] = useState(false);
  const [pollInsertOpen, setPollInsertOpen] = useState(false);
  const [wikiLinkPickerOpen, setWikiLinkPickerOpen] = useState(false);
  const [moveToModalOpen, setMoveToModalOpen] = useState(false);
  const [moveSourcePath, setMoveSourcePath] = useState('');

  const {
    fileTree,
    filteredTree,
    selectedFile,
    fileContent,
    dirty,
    saving,
    fileLoading,
    loading,
    fetchError,
    filterQuery,
    expandedKeys,
    modalType,
    modalInput,
    contextPath,
    config,
    setFilterQuery,
    setExpandedKeys,
    setModalType,
    setModalInput,
    setContextPath,
    fetchData,
    loadFile,
    saveFile,
    onContentChange,
    handleDelete,
    handleModalOk,
    handleMoveFile,
    handleNewFileRoot,
    handleNewFolderRoot,
    refreshTree,
    handleUploadFiles,
    isDirectoryPath,
    previewIframeRef,
    fileInputRef,
    contextHolder,
  } = editor;

  // --- Collaboration ---
  const collab = useDocsCollaboration(
    selectedFile?.endsWith('.md') ? selectedFile : null,
    collabEnabled,
  );

  // Bind Y.Text to textarea when both are ready
  useEffect(() => {
    if (yBindingRef.current) {
      yBindingRef.current.destroy();
      yBindingRef.current = null;
    }
    const ta = textareaRef.current;
    if (!collab.active || !collab.yText || !ta) return;

    const binding = new YTextareaBinding(collab.yText, ta);
    yBindingRef.current = binding;

    return () => {
      binding.destroy();
      yBindingRef.current = null;
    };
  }, [collab.active, collab.yText, selectedFile]);

  const treeData = useMemo(() => fileNodeToTreeData(filteredTree), [filteredTree]);

  // Flat file list for search results
  const allFiles = useMemo(() => flattenFiles(fileTree), [fileTree]);
  const searchResults = useMemo(() => {
    if (!filterQuery.trim() || filterQuery.length < 2) return [];
    const q = filterQuery.toLowerCase();
    return allFiles
      .filter(f => f.path.toLowerCase().includes(q) || f.name.toLowerCase().includes(q))
      .slice(0, 20);
  }, [filterQuery, allFiles]);

  // Helper: insert HTML at textarea cursor position
  const insertHtml = useCallback((html: string) => {
    const ta = textareaRef.current;
    if (!ta) {
      // No textarea — append to content
      onContentChange(fileContent + '\n' + html + '\n');
      return;
    }
    const { selectionStart, value } = ta;
    const before = value.substring(0, selectionStart);
    const after = value.substring(selectionStart);
    onContentChange(before + '\n' + html + '\n' + after);
  }, [onContentChange, fileContent]);

  const handleTreeSelect = useCallback(async (keys: React.Key[]) => {
    if (keys.length === 0) return;
    const path = keys[0] as string;
    if (isDirectoryPath(path)) return;

    if (dirty) {
      Modal.confirm({
        title: 'Unsaved Changes',
        content: 'Save changes before switching files?',
        okText: 'Save',
        cancelText: 'Discard',
        onOk: async () => {
          await saveFile();
          await loadFile(path);
          setActiveTab('editor');
        },
        onCancel: async () => {
          onContentChange(editor.fileContent);
          await loadFile(path);
          setActiveTab('editor');
        },
      });
      return;
    }

    await loadFile(path);
    setActiveTab('editor');
  }, [dirty, saveFile, loadFile, isDirectoryPath, onContentChange, editor.fileContent]);

  // Select file from search results
  const handleSearchSelect = useCallback(async (path: string) => {
    setSearchOpen(false);
    setFilterQuery('');
    await loadFile(path);
    setActiveTab('editor');
  }, [loadFile, setFilterQuery]);

  const handleTabChange = useCallback((val: string | number) => {
    const newTab = val as MobileTab;
    if (activeTab === 'editor' && newTab === 'files' && dirty) {
      Modal.confirm({
        title: 'Unsaved Changes',
        content: 'You have unsaved changes. Save before switching?',
        okText: 'Save',
        cancelText: 'Discard',
        onOk: async () => { await saveFile(); setActiveTab(newTab); },
        onCancel: () => setActiveTab(newTab),
      });
      return;
    }
    setActiveTab(newTab);
  }, [activeTab, dirty, saveFile]);

  const handleEditorChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {
    onContentChange(e.target.value);
  }, [onContentChange]);

  const handleFileInputChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files && e.target.files.length > 0) {
      handleUploadFiles(e.target.files);
      e.target.value = '';
    }
  }, [handleUploadFiles]);

  const toggleExpand = useCallback((key: string) => {
    setExpandedKeys(prev =>
      prev.includes(key)
        ? prev.filter(k => k !== key)
        : [...prev, key]
    );
  }, [setExpandedKeys]);

  const getContextMenuItems = useCallback((nodePath: string, isDir: boolean): MenuProps['items'] => {
    const items: MenuProps['items'] = [];
    if (isDir) {
      items.push(
        { key: 'newFile', icon: <FileAddOutlined />, label: 'New File', onClick: () => { setContextPath(nodePath); setModalInput(''); setModalType('newFile'); } },
        { key: 'newFolder', icon: <FolderAddOutlined />, label: 'New Folder', onClick: () => { setContextPath(nodePath); setModalInput(''); setModalType('newFolder'); } },
        { type: 'divider' },
      );
    }
    items.push(
      { key: 'rename', icon: <EditOutlined />, label: 'Rename', onClick: () => { setContextPath(nodePath); setModalInput(nodePath.split('/').pop() || ''); setModalType('rename'); } },
      { key: 'moveTo', icon: <FolderOpenOutlined />, label: 'Move to...', onClick: () => { setMoveSourcePath(nodePath); setMoveToModalOpen(true); } },
      { key: 'delete', icon: <DeleteOutlined />, label: 'Delete', danger: true, onClick: () => handleDelete(nodePath) },
    );
    return items;
  }, [setContextPath, setModalInput, setModalType, handleDelete]);

  const addMenuItems: MenuProps['items'] = useMemo(() => [
    { key: 'newFile', icon: <FileAddOutlined />, label: 'New File', onClick: handleNewFileRoot },
    { key: 'newFolder', icon: <FolderAddOutlined />, label: 'New Folder', onClick: handleNewFolderRoot },
    { key: 'upload', icon: <UploadOutlined />, label: 'Upload', onClick: () => fileInputRef.current?.click() },
    { type: 'divider' as const },
    { key: 'refresh', icon: <ReloadOutlined />, label: 'Refresh', onClick: refreshTree },
  ], [handleNewFileRoot, handleNewFolderRoot, fileInputRef, refreshTree]);

  // --- Insert handlers (mirror desktop logic but use insertHtml instead of Monaco) ---
  const handleInsertRequest = useCallback((type: InsertRequestType) => {
    switch (type) {
      case 'video-card': setVideoPickerOpen(true); break;
      case 'photo-insert': setPhotoInsertOpen(true); break;
      case 'donate-button': setDonateInsertOpen(true); break;
      case 'product-card': setProductInsertOpen(true); break;
      case 'ad-insert': setAdPickerOpen(true); break;
      case 'scheduling-poll': setPollInsertOpen(true); break;
      case 'wiki-link': setWikiLinkPickerOpen(true); break;
      case 'pricing-table': {
        const appUrl = config
          ? `${window.location.protocol}//${config.domain.replace(/^([^.]+)/, 'app')}`
          : window.location.origin;
        insertHtml(`<div style="text-align: center; padding: 40px 20px; background: linear-gradient(135deg, #1a1a2e, #16213e); border-radius: 12px; margin: 16px 0;">\n  <h2 style="color: #fff; margin: 12px 0;">Choose Your Plan</h2>\n  <p style="color: rgba(255,255,255,0.8); margin-bottom: 24px;">Get access to exclusive content and features.</p>\n  <a href="${appUrl}/pricing" style="display: inline-block; padding: 14px 36px; background: #722ed1; color: #fff; text-decoration: none; border-radius: 8px; font-weight: 600; font-size: 1.1rem;">View Plans</a>\n</div>`);
        break;
      }
    }
  }, [config, insertHtml]);

  const handleVideoCardInsert = useCallback((video: PickerVideo) => {
    const adminUrl = config
      ? `${window.location.protocol}//${config.domain.replace(/^([^.]+)/, 'app')}`
      : window.location.origin;
    const placeholderThumb = 'data:image/svg+xml,' + encodeURIComponent(
      '<svg xmlns="http://www.w3.org/2000/svg" width="480" height="270" viewBox="0 0 480 270"><rect fill="#0d1b2a" width="480" height="270"/><circle cx="240" cy="135" r="32" fill="rgba(157,78,221,0.6)"/><polygon points="230,118 258,135 230,152" fill="#fff"/></svg>'
    );
    const html = generateVideoCardHtml({
      id: video.id, title: video.title, durationSeconds: video.durationSeconds || 0,
      quality: '', viewCount: 0, thumbnailUrl: placeholderThumb,
    }, { baseUrl: adminUrl });
    insertHtml(html);
    setVideoPickerOpen(false);
  }, [config, insertHtml]);

  const handlePhotoInsert = useCallback((result: PhotoInsertResult) => {
    if (result.variant === 'single-photo' || result.variant === 'photo-card') {
      setPendingPhotoVariant(result);
      setPhotoPickerOpen(true);
      return;
    }
    const album = result.album;
    if (!album) return;
    let html = '';
    if (result.variant === 'album-grid') {
      const cols = result.options.columns || 3;
      const max = result.options.maxPhotos || 12;
      const title = result.options.showTitle !== false ? 'true' : 'false';
      html = `<div class="photo-album-block" data-album-id="${album.id}" data-columns="${cols}" data-max-photos="${max}" data-show-title="${title}">Loading album...</div>`;
    } else if (result.variant === 'album-carousel') {
      const max = result.options.maxPhotos || 20;
      const title = result.options.showTitle !== false ? 'true' : 'false';
      const auto = result.options.autoPlay ? 'true' : 'false';
      html = `<div class="photo-album-carousel" data-album-id="${album.id}" data-max-photos="${max}" data-show-title="${title}" data-auto-play="${auto}">Loading carousel...</div>`;
    }
    if (html) insertHtml(html);
  }, [insertHtml]);

  const handlePhotoSelected = useCallback((photo: PickerPhoto) => {
    const variant = pendingPhotoVariant?.variant || 'photo-card';
    if (variant === 'single-photo') {
      const opts = pendingPhotoVariant?.options || {};
      const html = `<div class="photo-block" data-photo-id="${photo.id}" data-size="${opts.size || 'large'}" data-caption="" data-link-to-gallery="${opts.linkToGallery !== false ? 'true' : 'false'}" data-alignment="${opts.alignment || 'center'}">Loading...</div>`;
      insertHtml(html);
    } else {
      const adminUrl = config
        ? `${window.location.protocol}//${config.domain.replace(/^([^.]+)/, 'app')}`
        : window.location.origin;
      const placeholderThumb = 'data:image/svg+xml,' + encodeURIComponent(
        '<svg xmlns="http://www.w3.org/2000/svg" width="480" height="320" viewBox="0 0 480 320"><rect fill="#0d1b2a" width="480" height="320"/><circle cx="240" cy="160" r="32" fill="rgba(46,125,50,0.6)"/></svg>'
      );
      const html = generatePhotoCardHtml({
        id: photo.id, title: photo.title || photo.originalFilename || 'Untitled Photo',
        description: photo.description || undefined, showMetadata: true,
        format: photo.format || undefined, width: photo.width || undefined,
        height: photo.height || undefined, viewCount: photo.viewCount || 0,
        thumbnailUrl: placeholderThumb,
      }, { baseUrl: adminUrl });
      insertHtml(html);
    }
    setPhotoPickerOpen(false);
    setPendingPhotoVariant(null);
  }, [config, pendingPhotoVariant, insertHtml]);

  const handleDonateInsert = useCallback((result: DonateInsertResult) => {
    if (result.variant === 'simple') {
      insertHtml('<div style="text-align: center; padding: 40px 20px; background: linear-gradient(135deg, #2d1b69, #1a1a2e); border-radius: 12px; margin: 16px 0;">\n  <p style="font-size: 48px; margin: 0;">&#x2764;&#xFE0F;</p>\n  <h2 style="color: #fff; margin: 12px 0;">Support Our Cause</h2>\n  <p style="color: rgba(255,255,255,0.8); margin-bottom: 24px;">Your contribution helps us create lasting change.</p>\n  <a href="/donate" style="display: inline-block; padding: 14px 36px; background: #eb2f96; color: #fff; text-decoration: none; border-radius: 8px; font-weight: 600;">Donate Now</a>\n</div>');
    } else if (result.variant === 'set-amount') {
      const cents = result.amount || 2500;
      const dollars = (cents / 100).toFixed(0);
      insertHtml(`<div data-amounts="${cents}" data-preselected="${cents}" style="text-align:center;padding:40px 20px;background:linear-gradient(135deg,#2d1b69,#1a1a2e);border-radius:12px;margin:16px 0;">\n  <h2 style="color:#fff;">Donate $${dollars}</h2>\n  <a href="/donate?amount=${cents}" style="display:inline-block;padding:14px 36px;background:#eb2f96;color:#fff;text-decoration:none;border-radius:8px;font-weight:600;">Donate $${dollars}</a>\n</div>`);
    } else {
      const cfg = result.config;
      const title = cfg?.donationPageTitle || 'Support Our Cause';
      insertHtml(`<div style="text-align:center;padding:40px 20px;background:linear-gradient(135deg,#2d1b69,#1a1a2e);border-radius:12px;margin:16px 0;">\n  <h2 style="color:#fff;">${title}</h2>\n  <a href="/donate" style="display:inline-block;padding:14px 36px;background:#eb2f96;color:#fff;text-decoration:none;border-radius:8px;font-weight:600;">Donate Now</a>\n</div>`);
    }
  }, [insertHtml]);

  const handleProductInsert = useCallback((result: ProductInsertResult) => {
    const p = result.product;
    const priceStr = `$${(p.priceCAD / 100).toFixed(2)}`;
    insertHtml(`<div data-product-id="${p.id}" style="text-align:center;padding:32px 20px;background:linear-gradient(135deg,#1a1a2e,#16213e);border-radius:12px;margin:16px 0;max-width:420px;margin-left:auto;margin-right:auto;">\n  <h3 style="color:#fff;">${p.title}</h3>\n  <p style="color:#fff;font-size:1.4rem;font-weight:700;">${priceStr}</p>\n  <a href="/shop" style="display:inline-block;padding:14px 36px;background:#722ed1;color:#fff;text-decoration:none;border-radius:8px;font-weight:600;">Buy Now</a>\n</div>`);
  }, [insertHtml]);

  const handleAdInsert = useCallback((result: AdInsertResult) => {
    const html = result.type === 'specific'
      ? `<div class="ad-specific-block" data-ad-id="${result.adId}" style="max-width:400px; margin:16px auto;">Loading ad...</div>`
      : `<div class="ad-slot-block" data-placement="docs" data-variant="${result.variant || 'standard'}" style="max-width:400px; margin:16px auto;">Loading ad...</div>`;
    insertHtml(html);
    setAdPickerOpen(false);
  }, [insertHtml]);

  const handlePollInsert = useCallback((slug: string) => {
    insertHtml(`<div class="scheduling-poll-block" data-poll-slug="${slug}" data-show-comments="true" data-title="Vote on a Meeting Time">Loading poll...</div>`);
    setPollInsertOpen(false);
  }, [insertHtml]);

  if (loading) {
    return <div style={{ textAlign: 'center', padding: 80 }}><Spin size="large" /></div>;
  }

  if (fetchError) {
    return (
      <Result
        status="error"
        title="Cannot Load Editor"
        subTitle="Failed to connect to the documentation services."
        extra={<Button type="primary" onClick={fetchData}>Retry</Button>}
      />
    );
  }

  const isMarkdownFile = selectedFile?.endsWith('.md');
  const isImage = selectedFile ? isImageFile(selectedFile) : false;
  const showSearchResults = searchOpen && filterQuery.trim().length >= 2;

  return (
    <>
      {contextHolder}

      <style>{`
        .mobile-docs-tree .ant-tree-treenode {
          padding: 0 !important;
          margin: 0 !important;
          min-height: 40px !important;
          line-height: 40px !important;
          border-radius: 0 !important;
          width: 100% !important;
        }
        .mobile-docs-tree .ant-tree-treenode:active {
          background: rgba(255,255,255,0.08) !important;
        }
        .mobile-docs-tree .ant-tree-node-content-wrapper {
          padding: 0 4px !important;
          min-height: 40px !important;
          line-height: 40px !important;
          border-radius: 0 !important;
          background: transparent !important;
        }
        .mobile-docs-tree .ant-tree-node-content-wrapper:hover {
          background: transparent !important;
        }
        .mobile-docs-tree .ant-tree-node-content-wrapper.ant-tree-node-selected {
          background: rgba(255,255,255,0.10) !important;
        }
        .mobile-docs-tree .ant-tree-switcher {
          width: 24px !important;
          height: 40px !important;
          line-height: 40px !important;
        }
        .mobile-docs-tree .ant-tree-indent-unit {
          width: 14px !important;
        }
        .mobile-docs-tree .ant-tree-list-holder-inner {
          padding: 0 !important;
        }
      `}</style>

      <div style={{ display: 'flex', flexDirection: 'column', height: 'calc(100dvh - 64px)' }}>
        {/* Header */}
        <div style={{
          height: 40,
          display: 'flex',
          alignItems: 'center',
          padding: '0 8px',
          gap: 6,
          borderBottom: `1px solid ${token.colorBorderSecondary}`,
          background: token.colorBgContainer,
          flexShrink: 0,
        }}>
          {searchOpen ? (
            <>
              <Input
                prefix={<SearchOutlined style={{ color: token.colorTextQuaternary, fontSize: 12 }} />}
                placeholder="Search files..."
                allowClear
                size="small"
                value={filterQuery}
                onChange={(e) => setFilterQuery(e.target.value)}
                style={{ flex: 1 }}
                autoFocus
              />
              <Button
                type="text"
                size="small"
                icon={<CloseOutlined style={{ fontSize: 12 }} />}
                onClick={() => { setSearchOpen(false); setFilterQuery(''); }}
                style={{ width: 28, height: 28, flexShrink: 0 }}
              />
            </>
          ) : (
            <>
              <Segmented
                size="small"
                value={activeTab}
                onChange={handleTabChange}
                options={[
                  { value: 'files', icon: <FolderOutlined /> },
                  { value: 'editor', icon: <CodeOutlined /> },
                  { value: 'preview', icon: <EyeOutlined /> },
                ]}
              />
              <div style={{ flex: 1 }} />
              <Button
                type="text"
                size="small"
                icon={<SearchOutlined style={{ fontSize: 14 }} />}
                onClick={() => setSearchOpen(true)}
                style={{ width: 28, height: 28 }}
              />
              {activeTab === 'files' && (
                <Dropdown menu={{ items: addMenuItems }} trigger={['click']} placement="bottomRight">
                  <Button type="text" size="small" icon={<PlusOutlined style={{ fontSize: 14 }} />} style={{ width: 28, height: 28 }} />
                </Dropdown>
              )}
              {isSuperAdmin && (
                <Button type="text" size="small" icon={<BuildOutlined style={{ fontSize: 14 }} />} onClick={confirmAndBuild} loading={building} style={{ width: 28, height: 28 }} />
              )}
            </>
          )}
        </div>

        <input
          ref={fileInputRef}
          type="file"
          multiple
          accept=".png,.jpg,.jpeg,.gif,.svg,.webp,.ico,.pdf,.zip,.md"
          style={{ display: 'none' }}
          onChange={handleFileInputChange}
        />

        {/* Tab content */}
        <div style={{ flex: 1, overflow: 'hidden', display: 'flex', flexDirection: 'column', minHeight: 0 }}>

          {/* Search results overlay */}
          {showSearchResults ? (
            <div style={{ flex: 1, overflow: 'auto' }}>
              {searchResults.length === 0 ? (
                <div style={{ padding: 24, textAlign: 'center', color: token.colorTextTertiary }}>
                  No files matching "{filterQuery}"
                </div>
              ) : (
                <List
                  size="small"
                  dataSource={searchResults}
                  renderItem={(item) => (
                    <List.Item
                      style={{ padding: '8px 12px', cursor: 'pointer' }}
                      onClick={() => handleSearchSelect(item.path)}
                    >
                      <div style={{ display: 'flex', alignItems: 'center', gap: 8, minWidth: 0 }}>
                        <FileOutlined style={{ fontSize: 12, color: token.colorTextSecondary, flexShrink: 0 }} />
                        <div style={{ minWidth: 0 }}>
                          <div style={{ fontSize: 13, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                            {item.name.replace(/\.md$/, '')}
                          </div>
                          <div style={{ fontSize: 11, color: token.colorTextTertiary, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                            {item.path}
                          </div>
                        </div>
                      </div>
                    </List.Item>
                  )}
                />
              )}
            </div>
          ) : (
            <>
              {/* FILES TAB */}
              {activeTab === 'files' && (
                <div style={{ flex: 1, overflow: 'auto' }} className="mobile-docs-tree">
                  <Tree
                    treeData={treeData}
                    showIcon={false}
                    showLine={false}
                    motion={false}
                    selectedKeys={selectedFile ? [selectedFile] : []}
                    expandedKeys={expandedKeys}
                    onExpand={(keys) => setExpandedKeys(keys)}
                    onSelect={(keys) => {
                      if (keys.length === 0) return;
                      const path = keys[0] as string;
                      if (isDirectoryPath(path)) return;
                      handleTreeSelect(keys);
                    }}
                    blockNode
                    titleRender={(nodeData) => {
                      const nodePath = nodeData.key as string;
                      const isDir = isDirectoryPath(nodePath);
                      return (
                        <div style={{ display: 'flex', alignItems: 'center', minHeight: 40 }}>
                          <span
                            onClick={(e) => {
                              if (isDir) { e.stopPropagation(); toggleExpand(nodePath); }
                            }}
                            style={{
                              flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
                              fontSize: 14, lineHeight: '40px',
                              color: isDir ? token.colorTextSecondary : token.colorText,
                              cursor: 'pointer',
                            }}
                          >
                            {nodeData.title as string}
                          </span>
                          <Dropdown menu={{ items: getContextMenuItems(nodePath, isDir) }} trigger={['click']} placement="bottomRight">
                            <Button type="text" size="small" icon={<EllipsisOutlined />} onClick={(e) => e.stopPropagation()} style={{ flexShrink: 0, width: 28, height: 40, opacity: 0.5 }} />
                          </Dropdown>
                        </div>
                      );
                    }}
                  />
                </div>
              )}

              {/* EDITOR TAB */}
              {activeTab === 'editor' && (
                <div style={{
                  display: 'flex', flexDirection: 'column', flex: 1, minHeight: 0,
                  paddingBottom: isMarkdownFile ? 'calc(56px + env(safe-area-inset-bottom, 0px))' : 0,
                }}>
                  {selectedFile && (
                    <div style={{
                      padding: '4px 10px',
                      borderBottom: `1px solid ${token.colorBorderSecondary}`,
                      display: 'flex', alignItems: 'center', gap: 6,
                      height: 28, flexShrink: 0,
                    }}>
                      <Typography.Text style={{ fontFamily: 'monospace', fontSize: 11, flex: 1, color: token.colorTextSecondary }} ellipsis>
                        {selectedFile}
                      </Typography.Text>
                      {collab.active && (
                        <CollaboratorAvatars collaborators={collab.collaborators} connected={collab.connected} />
                      )}
                      {dirty && !collab.active && (
                        <span style={{ width: 6, height: 6, borderRadius: '50%', background: token.colorWarning, flexShrink: 0 }} />
                      )}
                    </div>
                  )}

                  <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0, overflow: 'hidden' }}>
                    {fileLoading ? (
                      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%' }}><Spin /></div>
                    ) : !selectedFile ? (
                      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%', color: token.colorTextTertiary }}>
                        <div style={{ textAlign: 'center', padding: 24 }}>
                          <FileMarkdownOutlined style={{ fontSize: 48, marginBottom: 16 }} />
                          <div>Select a file from the Files tab</div>
                        </div>
                      </div>
                    ) : isImage ? (
                      <div style={{ padding: 16, textAlign: 'center', overflow: 'auto' }}>
                        <img src={`/mkdocs-proxy/${selectedFile}`} alt={selectedFile} style={{ maxWidth: '100%', maxHeight: 400, objectFit: 'contain', borderRadius: 4 }} />
                      </div>
                    ) : (
                      <LineNumberedEditor
                        textareaRef={textareaRef}
                        value={fileContent}
                        onChange={handleEditorChange}
                        token={token}
                      />
                    )}
                  </div>

                  {isMarkdownFile && selectedFile && !isImage && !fileLoading && (
                    <MobileFormattingToolbar
                      textareaRef={textareaRef}
                      dirty={dirty}
                      saving={saving}
                      onContentChange={onContentChange}
                      onSave={saveFile}
                      onInsertRequest={handleInsertRequest}
                    />
                  )}
                </div>
              )}

              {/* PREVIEW TAB */}
              {activeTab === 'preview' && (
                <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0 }}>
                  <div style={{
                    padding: '4px 10px', display: 'flex', alignItems: 'center', justifyContent: 'space-between',
                    borderBottom: `1px solid ${token.colorBorderSecondary}`, height: 28, flexShrink: 0,
                  }}>
                    <Typography.Text type="secondary" style={{ fontSize: 11 }}>{selectedFile || 'Home'}</Typography.Text>
                    <Button type="text" size="small" icon={<ReloadOutlined style={{ fontSize: 12 }} />} onClick={() => previewIframeRef.current?.contentWindow?.location.reload()} style={{ width: 24, height: 24 }} />
                  </div>
                  <iframe ref={previewIframeRef} src="/mkdocs-proxy/" style={{ flex: 1, width: '100%', border: 'none' }} title="MkDocs Preview" />
                </div>
              )}
            </>
          )}
        </div>
      </div>

      {/* File CRUD Modal */}
      <Modal
        title={modalType === 'newFile' ? 'New File' : modalType === 'newFolder' ? 'New Folder' : 'Rename'}
        open={modalType !== null}
        onOk={handleModalOk}
        onCancel={() => setModalType(null)}
        okText={modalType === 'rename' ? 'Rename' : 'Create'}
        destroyOnHidden
      >
        <Input
          placeholder={modalType === 'newFolder' ? 'Folder name' : 'File name (e.g. my-page.md)'}
          value={modalInput}
          onChange={(e) => setModalInput(e.target.value)}
          onPressEnter={handleModalOk}
          autoFocus
        />
        {contextPath && (
          <Typography.Text type="secondary" style={{ display: 'block', marginTop: 8, fontSize: 12 }}>
            {modalType === 'rename' ? `Renaming: ${contextPath}` : `Inside: ${contextPath}/`}
          </Typography.Text>
        )}
      </Modal>

      {/* Insert modals — same as desktop */}
      <VideoPickerModal open={videoPickerOpen} onClose={() => setVideoPickerOpen(false)} onSelect={handleVideoCardInsert} title="Insert Video Card" />
      <PhotoInsertModal open={photoInsertOpen} onClose={() => setPhotoInsertOpen(false)} onInsert={handlePhotoInsert} />
      <PhotoPickerModal open={photoPickerOpen} onClose={() => { setPhotoPickerOpen(false); setPendingPhotoVariant(null); }} onSelect={handlePhotoSelected} title={pendingPhotoVariant?.variant === 'single-photo' ? 'Select Photo' : 'Select Photo for Card'} />
      <DonateInsertModal open={donateInsertOpen} onClose={() => setDonateInsertOpen(false)} onInsert={handleDonateInsert} />
      <ProductInsertModal open={productInsertOpen} onClose={() => setProductInsertOpen(false)} onInsert={handleProductInsert} />
      <AdPickerModal open={adPickerOpen} onCancel={() => setAdPickerOpen(false)} onInsert={handleAdInsert} />
      <PollInsertModal open={pollInsertOpen} onCancel={() => setPollInsertOpen(false)} onInsert={handlePollInsert} />
      <WikiLinkPickerModal
        open={wikiLinkPickerOpen}
        fileTree={fileTree}
        onClose={() => setWikiLinkPickerOpen(false)}
        onSelect={(wikiLink) => {
          const ta = textareaRef.current;
          if (ta) {
            const { selectionStart, value } = ta;
            const before = value.substring(0, selectionStart);
            const after = value.substring(selectionStart);
            onContentChange(before + wikiLink + after);
            requestAnimationFrame(() => {
              ta.focus();
              const pos = selectionStart + wikiLink.length;
              ta.setSelectionRange(pos, pos);
            });
          } else {
            onContentChange(fileContent + wikiLink);
          }
          setWikiLinkPickerOpen(false);
        }}
      />

      <MoveToModal
        open={moveToModalOpen}
        fileTree={fileTree}
        sourcePath={moveSourcePath}
        onMove={(targetDir) => { setMoveToModalOpen(false); handleMoveFile(moveSourcePath, targetDir); }}
        onClose={() => setMoveToModalOpen(false)}
      />
    </>
  );
}
