'use client';

import React, { useRef, useState, useEffect } from 'react';

const baseInputClassName = 'w-full px-4 py-3 bg-white dark:bg-neutral-900/60 border rounded-xl text-sm text-neutral-900 dark:text-white placeholder-neutral-400 dark:placeholder-neutral-500 focus:outline-none focus:border-neutral-500 dark:focus:border-neutral-600 focus:ring-1 focus:ring-neutral-500/20 dark:focus:ring-neutral-600/20 hover:bg-neutral-50 dark:hover:bg-neutral-900/80 transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed resize-y min-h-[200px] font-mono ';
const toolbarBtnClassName = 'p-2 rounded-lg text-neutral-500 dark:text-neutral-400 hover:text-neutral-900 dark:hover:text-white hover:bg-neutral-200 dark:hover:bg-neutral-700/80 transition-colors disabled:opacity-50';

const UNDO_DEBOUNCE_MS = 600;
const MAX_HISTORY = 50;

/**
 * Reliable markdown editor: toolbar + textarea only. Single source of truth (value/onChange).
 * No preview mode to avoid sync bugs and contentEditable issues.
 */
function MarkdownEditor({
  value,
  onChange,
  placeholder = '',
  label,
  error,
  disabled = false,
  className = '',
  rows = 12,
  minHeight = '200px',
  ...props
}) {
  const textareaRef = useRef(null);
  const [undoStack, setUndoStack] = useState([]);
  const [redoStack, setRedoStack] = useState([]);
  const undoDebounceRef = useRef(null);

  const contentAreaClass = 'px-4 py-3 text-sm overflow-auto break-words leading-relaxed';
  const contentStyle = { minHeight };

  function pushUndo(prev) {
    if (prev === undefined || prev === null) return;
    setUndoStack(s => {
      const next = [...s, prev];
      return next.length > MAX_HISTORY ? next.slice(1) : next;
    });
    setRedoStack([]);
  }

  function handleUndo() {
    if (undoStack.length === 0) return;
    const prev = undoStack[undoStack.length - 1];
    setRedoStack(r => [...r, value ?? '']);
    setUndoStack(s => s.slice(0, -1));
    onChange?.(prev);
  }

  function handleRedo() {
    if (redoStack.length === 0) return;
    const next = redoStack[redoStack.length - 1];
    setUndoStack(u => [...u, value ?? '']);
    setRedoStack(r => r.slice(0, -1));
    onChange?.(next);
  }

  function applyChange(newText) {
    pushUndo(value ?? '');
    onChange?.(newText);
  }

  function handleTextareaChange(e) {
    const newText = e.target.value;
    const prev = value ?? '';
    if (undoDebounceRef.current) clearTimeout(undoDebounceRef.current);
    undoDebounceRef.current = setTimeout(() => {
      pushUndo(prev);
      undoDebounceRef.current = null;
    }, UNDO_DEBOUNCE_MS);
    onChange?.(newText);
  }

  useEffect(() => {
    return () => {
      if (undoDebounceRef.current) clearTimeout(undoDebounceRef.current);
    };
  }, []);

  function handleKeyDown(e) {
    if (e.key === 'z' && (e.ctrlKey || e.metaKey)) {
      e.preventDefault();
      if (e.shiftKey) handleRedo();
      else handleUndo();
    } else if (e.key === 'y' && (e.ctrlKey || e.metaKey)) {
      e.preventDefault();
      handleRedo();
    }
  }

  function insertOrWrap(before, after = before) {
    const ta = textareaRef.current;
    if (!ta) return;
    const start = ta.selectionStart;
    const end = ta.selectionEnd;
    const text = value ?? '';
    const selected = text.slice(start, end);

    const isWrapped = selected.length >= before.length + after.length &&
      selected.startsWith(before) &&
      selected.endsWith(after);

    let newSelected, newStart, newEnd;
    if (isWrapped) {
      newSelected = selected.slice(before.length, selected.length - after.length);
      newStart = start;
      newEnd = start + newSelected.length;
    } else {
      newSelected = before + selected + after;
      newStart = start + before.length;
      newEnd = start + before.length + selected.length;
    }

    const newText = text.slice(0, start) + newSelected + text.slice(end);
    applyChange(newText);
    setTimeout(() => {
      ta.focus();
      ta.setSelectionRange(newStart, newEnd);
    }, 0);
  }

  function insertOrWrapLink() {
    const ta = textareaRef.current;
    if (!ta) return;
    const start = ta.selectionStart;
    const end = ta.selectionEnd;
    const text = value ?? '';
    const selected = text.slice(start, end);
    const linkMatch = selected.match(/^\[([^\]]*)\]\([^)]*\)$/);
    if (linkMatch) {
      const inner = linkMatch[1];
      const newText = text.slice(0, start) + inner + text.slice(end);
      applyChange(newText);
      setTimeout(() => {
        ta.focus();
        ta.setSelectionRange(start, start + inner.length);
      }, 0);
    } else {
      insertOrWrap('[', '](url)');
    }
  }

  function insertLinePrefix(prefix) {
    const ta = textareaRef.current;
    if (!ta) return;
    const start = ta.selectionStart;
    const text = value ?? '';
    const lineStart = text.lastIndexOf('\n', start - 1) + 1;
    const lineEnd = text.indexOf('\n', lineStart);
    const line = text.slice(lineStart, lineEnd === -1 ? text.length : lineEnd);
    const hasPrefix = line.startsWith(prefix);

    let newText;
    let newCursor = start;
    if (hasPrefix) {
      newText = text.slice(0, lineStart) + line.slice(prefix.length) + text.slice(lineStart + line.length);
      newCursor = start <= lineStart + prefix.length ? lineStart : start - prefix.length;
    } else {
      newText = text.slice(0, lineStart) + prefix + text.slice(lineStart);
      newCursor = start + prefix.length;
    }
    applyChange(newText);
    setTimeout(() => {
      ta.focus();
      ta.setSelectionRange(newCursor, newCursor);
    }, 0);
  }

  const toolbar = [
    { label: 'B', title: 'Bold', action: () => insertOrWrap('**', '**') },
    { label: 'I', title: 'Italic', action: () => insertOrWrap('_', '_') },
    { label: 'Link', title: 'Link', action: () => insertOrWrapLink() },
    { label: 'Code', title: 'Code', action: () => insertOrWrap('`', '`') },
    { label: 'H1', title: 'Heading 1', action: () => insertLinePrefix('# ') },
    { label: 'H2', title: 'Heading 2', action: () => insertLinePrefix('## ') },
    { label: '•', title: 'Bullet list', action: () => insertLinePrefix('- ') },
    { label: '"', title: 'Quote', action: () => insertLinePrefix('> ') },
  ];

  return (
    <div className="space-y-2">
      {label && (
        <label className="block text-xs font-medium text-neutral-700 dark:text-neutral-400">
          {label}
        </label>
      )}
      <div className={`border rounded-xl overflow-hidden ${error ? 'border-red-500/50' : 'border-neutral-300 dark:border-neutral-700/50'}`}>
        <div className="flex flex-wrap items-center gap-0.5 p-1.5 bg-neutral-100 dark:bg-neutral-800/60 border-b border-neutral-200 dark:border-neutral-700/50">
          <button
            type="button"
            title="Undo (Ctrl+Z)"
            onClick={handleUndo}
            disabled={disabled || undoStack.length === 0}
            className={toolbarBtnClassName}
          >
            ←
          </button>
          <button
            type="button"
            title="Redo (Ctrl+Shift+Z)"
            onClick={handleRedo}
            disabled={disabled || redoStack.length === 0}
            className={toolbarBtnClassName}
          >
            →
          </button>
          <span className="w-px h-5 bg-neutral-300 dark:bg-neutral-600 mx-0.5" aria-hidden />
          {toolbar.map((btn) => (
            <button
              key={btn.label}
              type="button"
              title={btn.title}
              onClick={btn.action}
              disabled={disabled}
              className={toolbarBtnClassName}
            >
              {btn.label}
            </button>
          ))}
        </div>
        <textarea
          ref={textareaRef}
          value={value ?? ''}
          onChange={handleTextareaChange}
          onKeyDown={handleKeyDown}
          placeholder={placeholder}
          disabled={disabled}
          rows={rows}
          className={baseInputClassName + contentAreaClass + ' ' + (error ? 'border-red-500/50' : 'border-0') + ' ' + className}
          style={contentStyle}
          spellCheck="true"
          data-gramm="false"
          {...props}
        />
      </div>
      {error && (
        <p className="text-red-600 dark:text-red-400 text-xs">{error}</p>
      )}
    </div>
  );
}

export default MarkdownEditor;
