/**
 * Simple WYSIWYG Editor Field for Basic Editor
 *
 * A simplified Lexical editor with limited formatting options:
 * - Bold, Italic
 * - Text alignment (left, center, right)
 * - Links
 * - Unordered/Ordered lists
 *
 * Designed to match the dark theme of the Basic Editor.
 */

'use client';

import { useCallback, useEffect, useRef, useState } from 'react';
import { LexicalComposer } from '@lexical/react/LexicalComposer';
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
import { ContentEditable } from '@lexical/react/LexicalContentEditable';
import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin';
import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin';
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';
import { ListPlugin } from '@lexical/react/LexicalListPlugin';
import { LinkPlugin } from '@lexical/react/LexicalLinkPlugin';
import { ListNode, ListItemNode } from '@lexical/list';
import { LinkNode, AutoLinkNode } from '@lexical/link';
import { $generateHtmlFromNodes, $generateNodesFromDOM } from '@lexical/html';
import {
  $getRoot,
  $getSelection,
  FORMAT_TEXT_COMMAND,
  FORMAT_ELEMENT_COMMAND,
  EditorState,
  LexicalEditor,
  ElementFormatType,
} from 'lexical';
import { INSERT_ORDERED_LIST_COMMAND, INSERT_UNORDERED_LIST_COMMAND } from '@lexical/list';
import { ImageNode, ImagePlugin, ImageInsertPopover, INSERT_IMAGE_COMMAND } from './ImageNode';
import { EmbedNode, EmbedPlugin, INSERT_EMBED_COMMAND } from './EmbedNode';
import { useImageUpload } from '@/hooks/useImageUpload';
import { usePopoverPosition } from '@/hooks/usePopoverPosition';
import { LinkInsertPopover } from './LinkInsertPopover';
import { FloatingLinkEditorPlugin } from './FloatingLinkEditor';
import { sanitizeHtmlRelaxed } from './sanitize-client';
import { $selectionTouchesList } from './lexical-alignment-utils';

interface SimpleWysiwygFieldProps {
  value: string;
  onChange: (value: string) => void;
  placeholder?: string;
  enableMediaLibrary?: boolean;
}

// Toolbar button styles for dark theme
const toolbarButtonStyle: React.CSSProperties = {
  padding: '0.375rem 0.625rem',
  border: '1px solid rgba(255, 255, 255, 0.2)',
  borderRadius: '4px',
  background: 'rgba(255, 255, 255, 0.1)',
  color: 'rgba(255, 255, 255, 0.9)',
  cursor: 'pointer',
  fontSize: '0.875rem',
  minWidth: '2rem',
  transition: 'all 0.15s ease',
};

const toolbarButtonHoverStyle: React.CSSProperties = {
  background: 'rgba(255, 255, 255, 0.2)',
};

// Theme for Lexical editor (dark theme)
const theme = {
  paragraph: 'simple-wysiwyg-paragraph',
  list: {
    ul: 'simple-wysiwyg-list-ul',
    ol: 'simple-wysiwyg-list-ol',
    listitem: 'simple-wysiwyg-list-item',
  },
  link: 'simple-wysiwyg-link',
  text: {
    bold: 'simple-wysiwyg-text-bold',
    italic: 'simple-wysiwyg-text-italic',
  },
};

// Plugin to load initial HTML content
function InitialContentPlugin({ initialHtml }: { initialHtml: string }) {
  const [editor] = useLexicalComposerContext();
  const hasInitialized = useRef(false);

  useEffect(() => {
    if (hasInitialized.current || !initialHtml) return;
    hasInitialized.current = true;

    editor.update(() => {
      const parser = new DOMParser();
      const dom = parser.parseFromString(initialHtml, 'text/html');
      const nodes = $generateNodesFromDOM(editor, dom);
      const root = $getRoot();
      root.clear();
      nodes.forEach((node) => root.append(node));
    });
  }, [editor, initialHtml]);

  return null;
}

// Toolbar button component with hover effect
function ToolbarButton({
  onClick,
  title,
  ariaLabel,
  children,
  disabled = false,
}: {
  onClick: () => void;
  title: string;
  ariaLabel: string;
  children: React.ReactNode;
  disabled?: boolean;
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      disabled={disabled}
      style={{
        ...toolbarButtonStyle,
        ...(disabled ? { opacity: 0.4, cursor: 'not-allowed' } : {}),
      }}
      title={title}
      aria-label={ariaLabel}
      onMouseEnter={(e) => {
        if (disabled) return;
        Object.assign(e.currentTarget.style, toolbarButtonHoverStyle);
      }}
      onMouseLeave={(e) => {
        if (disabled) return;
        e.currentTarget.style.background = 'rgba(255, 255, 255, 0.1)';
      }}
    >
      {children}
    </button>
  );
}

// Embed insert popover component
function EmbedInsertPopover({
  editor,
  onClose,
  triggerRef,
}: {
  editor: LexicalEditor;
  onClose: () => void;
  triggerRef: React.RefObject<HTMLElement | null>;
}) {
  const [embedCode, setEmbedCode] = useState('');
  const [preview, setPreview] = useState('');
  const popoverRef = useRef<HTMLDivElement>(null);
  const textareaRef = useRef<HTMLTextAreaElement>(null);
  // isOpen is always true because EmbedInsertPopover is conditionally mounted
  // (only rendered when showEmbedPopover is true), so it's always "open" when it exists
  const popoverPosition = usePopoverPosition(triggerRef, popoverRef, true);

  useEffect(() => {
    textareaRef.current?.focus();
  }, []);

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

  const handlePreview = useCallback(() => {
    if (embedCode.trim()) {
      setPreview(sanitizeHtmlRelaxed(embedCode.trim()));
    }
  }, [embedCode]);

  const handleInsert = useCallback(() => {
    const sanitized = sanitizeHtmlRelaxed(embedCode.trim());
    if (!sanitized) return;

    editor.focus();
    // Raw HTML is dispatched intentionally — EmbedNode sanitizes at render time
    // (see EmbedNode.tsx). Do not remove render-time sanitization thinking this is already clean.
    editor.dispatchCommand(INSERT_EMBED_COMMAND, { html: embedCode.trim() });
    onClose();
  }, [editor, embedCode, onClose]);

  return (
    <div
      ref={popoverRef}
      style={{
        position: 'absolute',
        top: popoverPosition.top,
        bottom: popoverPosition.bottom,
        left: popoverPosition.left,
        right: popoverPosition.right,
        zIndex: 1000,
        background: 'rgba(30, 41, 59, 0.95)',
        border: '1px solid rgba(148, 163, 184, 0.25)',
        borderRadius: '12px',
        padding: '16px',
        boxShadow: '0 4px 12px rgba(0,0,0,0.3)',
        minWidth: '360px',
        maxWidth: '480px',
      }}
    >
      <div style={{ marginBottom: '8px', fontSize: '14px', color: 'rgba(148, 163, 184, 0.85)' }}>
        Paste embed code (iframe, YouTube, Google Maps, etc.)
      </div>
      <textarea
        ref={textareaRef}
        value={embedCode}
        onChange={(e) => setEmbedCode(e.target.value)}
        placeholder='<iframe src="https://..." ...></iframe>'
        style={{
          width: '100%',
          minHeight: '80px',
          padding: '12px 16px',
          background: 'rgba(15, 23, 42, 0.75)',
          border: '1px solid rgba(148, 163, 184, 0.25)',
          borderRadius: '8px',
          color: '#f8fafc',
          fontSize: '13px',
          fontFamily: 'monospace',
          resize: 'vertical',
        }}
      />
      {preview && (
        <div
          style={{
            marginTop: '8px',
            padding: '8px',
            background: 'rgba(255,255,255,0.05)',
            borderRadius: '4px',
            border: '1px solid rgba(255,255,255,0.1)',
            maxHeight: '200px',
            overflow: 'auto',
          }}
        >
          <div
            style={{ fontSize: '0.6875rem', color: 'rgba(255,255,255,0.5)', marginBottom: '4px' }}
          >
            Preview:
          </div>
          <div dangerouslySetInnerHTML={{ __html: preview }} style={{ maxWidth: '100%' }} />
        </div>
      )}
      <div style={{ display: 'flex', gap: '8px', marginTop: '12px', justifyContent: 'flex-end' }}>
        <button
          type="button"
          onClick={handlePreview}
          disabled={!embedCode.trim()}
          style={{
            padding: '8px 16px',
            background: 'transparent',
            border: '1px solid #38bdf8',
            borderRadius: '8px',
            color: '#38bdf8',
            cursor: embedCode.trim() ? 'pointer' : 'not-allowed',
            fontSize: '14px',
            fontWeight: 600,
            opacity: embedCode.trim() ? 1 : 0.5,
          }}
        >
          Preview
        </button>
        <button
          type="button"
          onClick={handleInsert}
          disabled={!embedCode.trim()}
          style={{
            padding: '8px 16px',
            background: embedCode.trim() ? '#38bdf8' : 'rgba(71, 85, 105, 0.4)',
            border: 'none',
            borderRadius: '8px',
            color: embedCode.trim() ? '#0f172a' : 'rgba(226, 232, 240, 0.65)',
            cursor: embedCode.trim() ? 'pointer' : 'not-allowed',
            fontSize: '14px',
            fontWeight: 600,
          }}
        >
          Insert
        </button>
      </div>
    </div>
  );
}

// Toolbar component with limited options
function SimpleToolbar({ enableMediaLibrary }: { enableMediaLibrary?: boolean }) {
  const [editor] = useLexicalComposerContext();
  const imageInputRef = useRef<HTMLInputElement>(null);
  const imageTriggerRef = useRef<HTMLDivElement>(null);
  const embedTriggerRef = useRef<HTMLDivElement>(null);
  const linkTriggerRef = useRef<HTMLDivElement>(null);
  const [showImagePopover, setShowImagePopover] = useState(false);
  const [showEmbedPopover, setShowEmbedPopover] = useState(false);
  const [showLinkPopover, setShowLinkPopover] = useState(false);
  // Alignment is disabled inside lists: Lexical exports <li text-align> but
  // never re-imports it, so it would silently vanish on the next edit.
  const [alignDisabled, setAlignDisabled] = useState(false);
  const { uploadImage, isUploading } = useImageUpload();

  // Disable alignment when the selection touches a list. FORMAT_ELEMENT_COMMAND
  // formats the block ancestor of every node in the selection, so a selection
  // that merely extends into a list would still write non-round-tripping
  // alignment onto the list items.
  useEffect(() => {
    return editor.registerUpdateListener(({ editorState }) => {
      editorState.read(() => {
        setAlignDisabled($selectionTouchesList($getSelection()));
      });
    });
  }, [editor]);

  const handleImageUpload = useCallback(
    async (e: React.ChangeEvent<HTMLInputElement>) => {
      const file = e.target.files?.[0];
      if (!file) return;

      try {
        const url = await uploadImage(file, 'general');
        editor.focus();
        editor.dispatchCommand(INSERT_IMAGE_COMMAND, {
          src: url,
          altText: file.name.replace(/\.[^.]+$/, ''),
        });
      } catch {
        // Error is handled by the useImageUpload hook
      }

      if (imageInputRef.current) {
        imageInputRef.current.value = '';
      }
    },
    [editor, uploadImage]
  );

  const formatBold = useCallback(() => {
    editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'bold');
  }, [editor]);

  const formatItalic = useCallback(() => {
    editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'italic');
  }, [editor]);

  const formatAlign = useCallback(
    (alignment: ElementFormatType) => {
      editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, alignment);
    },
    [editor]
  );

  const formatBulletList = useCallback(() => {
    editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, undefined);
  }, [editor]);

  const formatNumberedList = useCallback(() => {
    editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, undefined);
  }, [editor]);

  return (
    <div
      role="toolbar"
      aria-label="Text formatting"
      style={{
        display: 'flex',
        flexWrap: 'wrap',
        gap: '0.375rem',
        padding: '0.625rem',
        borderBottom: '1px solid rgba(255, 255, 255, 0.1)',
        background: 'rgba(0, 0, 0, 0.2)',
        borderTopLeftRadius: '6px',
        borderTopRightRadius: '6px',
        overflow: 'visible',
        position: 'relative',
      }}
    >
      {/* Text Formatting */}
      <ToolbarButton onClick={formatBold} title="Bold" ariaLabel="Bold">
        <strong>B</strong>
      </ToolbarButton>
      <ToolbarButton onClick={formatItalic} title="Italic" ariaLabel="Italic">
        <em>I</em>
      </ToolbarButton>

      <span style={{ width: '1px', background: 'rgba(255, 255, 255, 0.2)', margin: '0 0.25rem' }} />

      {/* Alignment (disabled inside lists — see alignDisabled) */}
      <ToolbarButton
        onClick={() => formatAlign('left')}
        title={alignDisabled ? 'Alignment is not available inside lists' : 'Align Left'}
        ariaLabel="Align Left"
        disabled={alignDisabled}
      >
        <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
          <path d="M3 3h18v2H3V3zm0 4h12v2H3V7zm0 4h18v2H3v-2zm0 4h12v2H3v-2zm0 4h18v2H3v-2z" />
        </svg>
      </ToolbarButton>
      <ToolbarButton
        onClick={() => formatAlign('center')}
        title={alignDisabled ? 'Alignment is not available inside lists' : 'Align Center'}
        ariaLabel="Align Center"
        disabled={alignDisabled}
      >
        <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
          <path d="M3 3h18v2H3V3zm3 4h12v2H6V7zm-3 4h18v2H3v-2zm3 4h12v2H6v-2zm-3 4h18v2H3v-2z" />
        </svg>
      </ToolbarButton>
      <ToolbarButton
        onClick={() => formatAlign('right')}
        title={alignDisabled ? 'Alignment is not available inside lists' : 'Align Right'}
        ariaLabel="Align Right"
        disabled={alignDisabled}
      >
        <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
          <path d="M3 3h18v2H3V3zm6 4h12v2H9V7zm-6 4h18v2H3v-2zm6 4h12v2H9v-2zm-6 4h18v2H3v-2z" />
        </svg>
      </ToolbarButton>

      <span style={{ width: '1px', background: 'rgba(255, 255, 255, 0.2)', margin: '0 0.25rem' }} />

      {/* Lists */}
      <ToolbarButton onClick={formatBulletList} title="Bullet List" ariaLabel="Bullet List">
        <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
          <path d="M4 6a2 2 0 1 1 0-4 2 2 0 0 1 0 4zm0 8a2 2 0 1 1 0-4 2 2 0 0 1 0 4zm0 8a2 2 0 1 1 0-4 2 2 0 0 1 0 4zm4-15h14v2H8V5zm0 8h14v2H8v-2zm0 8h14v2H8v-2z" />
        </svg>
      </ToolbarButton>
      <ToolbarButton onClick={formatNumberedList} title="Numbered List" ariaLabel="Numbered List">
        <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
          <path d="M2 5h2v2H3v1h1v1H2V7h1V6H2V5zm0 7h3v1H3v1h2v1H2v-3zm1 7v-1h1v-1H2v4h3v-1H3v-1zm5-12h14v2H8V5zm0 6h14v2H8v-2zm0 6h14v2H8v-2z" />
        </svg>
      </ToolbarButton>

      <span style={{ width: '1px', background: 'rgba(255, 255, 255, 0.2)', margin: '0 0.25rem' }} />

      {/* Link */}
      <div ref={linkTriggerRef} style={{ position: 'relative' }}>
        <ToolbarButton
          onClick={() => setShowLinkPopover(!showLinkPopover)}
          title="Add Link"
          ariaLabel="Add Link"
        >
          <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
            <path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7a5 5 0 0 0 0 10h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4a5 5 0 0 0 0-10z" />
          </svg>
        </ToolbarButton>
        {showLinkPopover && (
          <LinkInsertPopover
            editor={editor}
            onClose={() => setShowLinkPopover(false)}
            triggerRef={linkTriggerRef}
          />
        )}
      </div>

      <span style={{ width: '1px', background: 'rgba(255, 255, 255, 0.2)', margin: '0 0.25rem' }} />

      {/* Image Upload */}
      <input
        ref={imageInputRef}
        type="file"
        accept="image/jpeg,image/png,image/webp"
        style={{ display: 'none' }}
        onChange={handleImageUpload}
      />
      <div ref={imageTriggerRef} style={{ position: 'relative' }}>
        <ToolbarButton
          onClick={() => {
            if (isUploading) return;
            if (enableMediaLibrary) {
              setShowImagePopover(!showImagePopover);
            } else {
              imageInputRef.current?.click();
            }
          }}
          title="Insert Image"
          ariaLabel="Insert Image"
        >
          {isUploading ? (
            <span style={{ fontSize: '14px' }}>...</span>
          ) : (
            <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
              <path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z" />
            </svg>
          )}
        </ToolbarButton>
        {showImagePopover && (
          <ImageInsertPopover
            editor={editor}
            onClose={() => setShowImagePopover(false)}
            onUploadClick={() => imageInputRef.current?.click()}
            variant="dark"
            triggerRef={imageTriggerRef}
          />
        )}
      </div>

      <span style={{ width: '1px', background: 'rgba(255, 255, 255, 0.2)', margin: '0 0.25rem' }} />

      {/* Embed Code */}
      <div ref={embedTriggerRef} style={{ position: 'relative' }}>
        <ToolbarButton
          onClick={() => setShowEmbedPopover(!showEmbedPopover)}
          title="Insert Embed Code"
          ariaLabel="Insert Embed Code"
        >
          <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
            <path d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0L19.2 12l-4.6-4.6L16 6l6 6-6 6-1.4-1.4z" />
          </svg>
        </ToolbarButton>
        {showEmbedPopover && (
          <EmbedInsertPopover
            editor={editor}
            onClose={() => setShowEmbedPopover(false)}
            triggerRef={embedTriggerRef}
          />
        )}
      </div>
    </div>
  );
}

export function SimpleWysiwygField({
  value,
  onChange,
  placeholder = 'Start typing...',
  enableMediaLibrary,
}: SimpleWysiwygFieldProps) {
  const editorContainerRef = useRef<HTMLDivElement>(null);

  const initialConfig = {
    namespace: 'SimpleWysiwygEditor',
    theme,
    onError: (error: Error) => {
      console.error('Lexical error:', error);
    },
    nodes: [ListNode, ListItemNode, LinkNode, AutoLinkNode, ImageNode, EmbedNode],
  };

  const handleChange = useCallback(
    (editorState: EditorState, editor: LexicalEditor) => {
      editorState.read(() => {
        const html = $generateHtmlFromNodes(editor, null);
        onChange(html);
      });
    },
    [onChange]
  );

  return (
    <div
      ref={editorContainerRef}
      className="simple-wysiwyg-root"
      style={{
        border: '1px solid rgba(75, 85, 99, 1)',
        borderRadius: '6px',
        overflow: 'visible',
        background: 'rgba(31, 41, 55, 0.3)',
        position: 'relative',
      }}
    >
      <LexicalComposer initialConfig={initialConfig}>
        <SimpleToolbar enableMediaLibrary={enableMediaLibrary} />
        <div
          style={{
            position: 'relative',
            minHeight: '120px',
            overflow: 'hidden',
            borderBottomLeftRadius: '6px',
            borderBottomRightRadius: '6px',
          }}
        >
          <RichTextPlugin
            contentEditable={
              <ContentEditable
                className="simple-wysiwyg-content"
                style={{
                  outline: 'none',
                  minHeight: '120px',
                  padding: '0.75rem 1rem',
                  color: 'white',
                }}
              />
            }
            placeholder={
              <div
                style={{
                  position: 'absolute',
                  top: '0.75rem',
                  left: '1rem',
                  color: 'rgba(107, 114, 128, 1)',
                  pointerEvents: 'none',
                }}
              >
                {placeholder}
              </div>
            }
            ErrorBoundary={LexicalErrorBoundary}
          />
        </div>
        <HistoryPlugin />
        <ListPlugin />
        <LinkPlugin />
        <OnChangePlugin onChange={handleChange} />
        <InitialContentPlugin initialHtml={value || ''} />
        <FloatingLinkEditorPlugin anchorRef={editorContainerRef} />
        <ImagePlugin />
        <EmbedPlugin />
      </LexicalComposer>

      {/* Scoped styles for the editor */}
      <style>{`
        .simple-wysiwyg-content {
          min-height: 120px;
          padding: 0.75rem 1rem;
        }
        .simple-wysiwyg-content:focus {
          outline: none;
        }
        .simple-wysiwyg-paragraph {
          margin: 0 0 0.75em 0;
          line-height: 1.6;
        }
        .simple-wysiwyg-paragraph:last-child {
          margin-bottom: 0;
        }
        .simple-wysiwyg-list-ul {
          margin: 0 0 0.75em 0;
          padding-left: 1.5em;
          line-height: 1.6;
          list-style: disc;
        }
        .simple-wysiwyg-list-ol {
          margin: 0 0 0.75em 0;
          padding-left: 1.5em;
          line-height: 1.6;
          list-style: decimal;
        }
        .simple-wysiwyg-list-item {
          margin: 0.25em 0;
        }
        .simple-wysiwyg-link {
          color: #38bdf8;
          text-decoration: underline;
        }
        .simple-wysiwyg-link:hover {
          color: #7dd3fc;
        }
        .simple-wysiwyg-text-bold {
          font-weight: 600;
        }
        .simple-wysiwyg-text-italic {
          font-style: italic;
        }
      `}</style>
    </div>
  );
}
