import React, { useRef, useEffect, useState } from 'react';
import type { CBNode } from '../../types';
import type { EditorStore } from '../../store/editorStore';
import { activeDrag } from './CanvasNode';

interface Props {
  node: CBNode;
  store: EditorStore;
  parentRef: React.RefObject<HTMLElement>;
  onStartEdit: () => void;
}

// ── Reference-style SVG icons (stroke-based, crisp on the purple bar) ──
const stroke = { fill: 'none', stroke: 'currentColor', strokeWidth: 2, strokeLinecap: 'round' as const, strokeLinejoin: 'round' as const };
const IcDrag = (
  <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
    <circle cx="9" cy="6" r="1.6"/><circle cx="15" cy="6" r="1.6"/>
    <circle cx="9" cy="12" r="1.6"/><circle cx="15" cy="12" r="1.6"/>
    <circle cx="9" cy="18" r="1.6"/><circle cx="15" cy="18" r="1.6"/>
  </svg>
);
const IcUp = (<svg width="14" height="14" viewBox="0 0 24 24" {...stroke}><path d="M12 19V5M5 12l7-7 7 7"/></svg>);
const IcDown = (<svg width="14" height="14" viewBox="0 0 24 24" {...stroke}><path d="M12 5v14M19 12l-7 7-7-7"/></svg>);
const IcDuplicate = (
  <svg width="14" height="14" viewBox="0 0 24 24" {...stroke}>
    <rect x="9" y="9" width="11" height="11" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/>
  </svg>
);
const IcTrash = (
  <svg width="14" height="14" viewBox="0 0 24 24" {...stroke}>
    <path d="M3 6h18M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/>
  </svg>
);
const IcTrashAll = (
  <svg width="14" height="14" viewBox="0 0 24 24" {...stroke}>
    <path d="M3 6h18M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/>
    <path d="M10 11v6M14 11v6"/>
  </svg>
);
const IcKebab = (
  <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
    <circle cx="12" cy="5" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="12" cy="19" r="1.6"/>
  </svg>
);
const IcEdit = (<svg width="13" height="13" viewBox="0 0 24 24" {...stroke}><path d="M12 20h9M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z"/></svg>);
const IcLink = (<svg width="14" height="14" viewBox="0 0 24 24" {...stroke}><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>);
const IcCopy = (<svg width="13" height="13" viewBox="0 0 24 24" {...stroke}><rect x="9" y="9" width="11" height="11" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/></svg>);
const IcAdd = (<svg width="14" height="14" viewBox="0 0 24 24" {...stroke}><path d="M12 5v14M5 12h14"/></svg>);
const IcSettings = (<svg width="13" height="13" viewBox="0 0 24 24" {...stroke}><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z"/></svg>);

const BLOCK_ICON = (
  <svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor">
    <rect x="3" y="7" width="18" height="10" rx="1.5"/>
  </svg>
);

const COL_ICONS: Record<number, React.ReactElement> = {
  2: (
    <svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor">
      <rect x="3" y="4" width="7.5" height="16" rx="1.5"/>
      <rect x="13.5" y="4" width="7.5" height="16" rx="1.5"/>
    </svg>
  ),
  3: (
    <svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor">
      <rect x="2"    y="4" width="5.5" height="16" rx="1.5"/>
      <rect x="9.25" y="4" width="5.5" height="16" rx="1.5"/>
      <rect x="16.5" y="4" width="5.5" height="16" rx="1.5"/>
    </svg>
  ),
  4: (
    <svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor">
      <rect x="2"  y="4" width="3.5" height="16" rx="1.5"/>
      <rect x="7"  y="4" width="3.5" height="16" rx="1.5"/>
      <rect x="12" y="4" width="3.5" height="16" rx="1.5"/>
      <rect x="17" y="4" width="3.5" height="16" rx="1.5"/>
    </svg>
  ),
};

export function FloatingToolbar({ node, store, onStartEdit }: Props) {
  const canEdit    = ['heading', 'text', 'button'].includes(node.type);
  const isSection  = node.type === 'section';
  const isContainer = node.type === 'container';
  const sections   = store.state.pageData.sections;
  const sectionIdx = sections.findIndex((s) => s.id === node.id);

  const colChildren  = isContainer ? (node.children ?? []).filter((c) => c.type === 'column') : [];
  const hasColumns   = isContainer && colChildren.length > 0
    && (node.children ?? []).every((c) => c.type === 'column');
  const currentCols  = hasColumns ? colChildren.length : 1;

  const [menuOpen, setMenuOpen] = useState(false);
  const menuRef = useRef<HTMLDivElement>(null);
  useEffect(() => {
    if (!menuOpen) return;
    const onDoc = (e: MouseEvent) => {
      if (menuRef.current && !menuRef.current.contains(e.target as Node)) setMenuOpen(false);
    };
    document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, [menuOpen]);

  // Position of this node among its SIBLINGS (top-level sections OR a parent's
  // children) — so move up/down works for every element, not only sections.
  const findSiblings = (nodes: CBNode[]): CBNode[] | null => {
    if (nodes.some((n) => n.id === node.id)) return nodes;
    for (const n of nodes) {
      if (n.children) {
        const found = findSiblings(n.children);
        if (found) return found;
      }
    }
    return null;
  };
  const siblings = isSection ? sections : (findSiblings(sections) ?? []);
  const myIdx    = siblings.findIndex((s) => s.id === node.id);
  const canMoveUp   = myIdx > 0;
  const canMoveDown = myIdx !== -1 && myIdx < siblings.length - 1;

  // Positioning: a toolbar floating ABOVE a node lands in the gap over the
  // PREVIOUS element, so for stacked sections/containers it looks hidden. Those
  // structural nodes therefore render the toolbar just INSIDE their own top edge
  // (always visible, never overlapping a neighbour). Small inline elements
  // (heading/text/button/etc.) keep the above position — but still flip inside
  // when there's no room above (near the top of the scroll area).
  const structural = isSection || isContainer || node.type === 'column';
  const barRef = useRef<HTMLDivElement>(null);
  const [flip, setFlip] = useState(structural);
  useEffect(() => {
    if (structural) { setFlip(true); return; }
    const el = barRef.current?.parentElement;
    if (!el) return;
    const check = () => {
      const r = el.getBoundingClientRect();
      const scroller = el.closest('.jalpi-canvas, .jalpi-canvas-scroll, [data-canvas-scroll]') as HTMLElement | null;
      const topLimit = scroller ? scroller.getBoundingClientRect().top : 0;
      // 48px = toolbar height + gap; flip when there isn't room above.
      setFlip(r.top - topLimit < 48);
    };
    check();
    const scroller = el.closest('.jalpi-canvas, .jalpi-canvas-scroll, [data-canvas-scroll]');
    scroller?.addEventListener('scroll', check, { passive: true });
    window.addEventListener('resize', check);
    return () => { scroller?.removeEventListener('scroll', check); window.removeEventListener('resize', check); };
  }, []);

  return (
    <div
      ref={barRef}
      className={`jalpi-floating-toolbar${flip ? ' is-flipped' : ''}`}
      onClick={(e) => e.stopPropagation()}
      onMouseDown={(e) => e.stopPropagation()}
      draggable={false}
      onDragStart={(e) => { e.preventDefault(); e.stopPropagation(); }}
    >
      {/* drag handle — draggable so it moves the node (the toolbar itself is not
         draggable, so buttons register clicks cleanly). */}
      <button
        className="jalpi-floating-toolbar__btn jalpi-floating-toolbar__handle"
        title="Drag to move" tabIndex={-1}
        draggable
        onDragStart={(e) => {
          e.stopPropagation();
          activeDrag.sourceId = node.id;
          activeDrag.sourceNode = node;
          e.dataTransfer.effectAllowed = 'move';
          e.dataTransfer.setData('text/plain', node.id);
        }}
      >
        {IcDrag}
      </button>

      <span className="jalpi-floating-toolbar__sep" />

      {canEdit && (
        <button className="jalpi-floating-toolbar__btn" title="Edit text" onClick={onStartEdit}>
          {IcEdit}
        </button>
      )}

      {/* move up / down — every element, reordered within its parent */}
      <button className="jalpi-floating-toolbar__btn" title="Move up" disabled={!canMoveUp}
        onClick={() => canMoveUp && store.moveNode(node.id, 'up')}>{IcUp}</button>
      <button className="jalpi-floating-toolbar__btn" title="Move down" disabled={!canMoveDown}
        onClick={() => canMoveDown && store.moveNode(node.id, 'down')}>{IcDown}</button>

      {/* duplicate */}
      <button className="jalpi-floating-toolbar__btn" title="Duplicate (⌘D)"
        onClick={() => store.duplicateNode(node.id)}>{IcDuplicate}</button>

      {/* link — for link-capable elements; opens properties where the link field lives */}
      {['button', 'heading', 'text', 'image'].includes(node.type) && (
        <button className="jalpi-floating-toolbar__btn" title="Link"
          onClick={() => store.selectNode(node.id)}>{IcLink}</button>
      )}

      {/* settings — open the properties panel for this element */}
      <button className="jalpi-floating-toolbar__btn" title="Settings"
        onClick={() => store.selectNode(node.id)}>{IcSettings}</button>

      {/* delete */}
      <button className="jalpi-floating-toolbar__btn jalpi-floating-toolbar__btn--danger" title="Delete"
        onClick={() => store.deleteNode(node.id)}>{IcTrash}</button>

      {isContainer && (
        <>
          <span className="jalpi-floating-toolbar__sep" />
          <button
            className={`jalpi-floating-toolbar__btn jalpi-floating-toolbar__col-btn${!hasColumns ? ' is-active' : ''}`}
            title="Block layout (single column)"
            onClick={() => store.setContainerColumns(node.id, 1)}
          >
            {BLOCK_ICON}
          </button>
          {[2, 3, 4].map((n) => (
            <button
              key={n}
              className={`jalpi-floating-toolbar__btn jalpi-floating-toolbar__col-btn${hasColumns && currentCols === n ? ' is-active' : ''}`}
              title={`${n}-column layout`}
              onClick={() => store.setContainerColumns(node.id, n)}
            >
              {COL_ICONS[n]}
            </button>
          ))}
        </>
      )}

      <span className="jalpi-floating-toolbar__sep" />

      {/* kebab overflow menu (copy / add section / delete-all) */}
      <div className="jalpi-floating-toolbar__menu-wrap" ref={menuRef}>
        <button className="jalpi-floating-toolbar__btn" title="More" onClick={() => setMenuOpen((o) => !o)}>
          {IcKebab}
        </button>
        {menuOpen && (
          <div className="jalpi-floating-toolbar__menu">
            <button className="jalpi-floating-toolbar__menu-item"
              onClick={() => { store.copyNode(node.id); setMenuOpen(false); }}>
              {IcCopy}<span>Copy</span>
            </button>
            {isSection && (
              <button className="jalpi-floating-toolbar__menu-item"
                onClick={() => { store.addSection(node.id); setMenuOpen(false); }}>
                {IcAdd}<span>Add section below</span>
              </button>
            )}
            <button className="jalpi-floating-toolbar__menu-item"
              onClick={() => { store.duplicateNode(node.id); setMenuOpen(false); }}>
              {IcDuplicate}<span>Duplicate</span>
            </button>
            <div className="jalpi-floating-toolbar__menu-sep" />
            <button className="jalpi-floating-toolbar__menu-item jalpi-floating-toolbar__menu-item--danger"
              onClick={() => { store.deleteNode(node.id); setMenuOpen(false); }}>
              {IcTrashAll}<span>Delete</span>
            </button>
          </div>
        )}
      </div>
    </div>
  );
}
