'use client';

import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';
import {
  TextColorIcon,
  HighlighterIcon,
  Link02Icon,
  CodeSimpleIcon,
  TextClearIcon,
  ArrowDown01Icon,
} from '@zen/core/shared/icons';
import { INLINE_COLORS, INLINE_COLOR_KEYS, markKey } from './types.js';
import {
  BOX_CLASS,
  ICON_BTN_CLASS,
  ICON_BTN_ACTIVE_CLASS,
  SEPARATOR_VERTICAL_CLASS,
} from './menuStyles.js';

// Toolbar flottant de formatage. Rendu en `position: absolute` à l'intérieur
// du container relatif du BlockEditor : il scrolle naturellement avec le
// texte. `rect` est exprimé en coords locales au container (top/left/bottom
// relatifs au content origin du container). La décision flip-up vs flip-down
// utilise la position viewport du container pour rester proche de la
// sélection visible.

const TOOLBAR_HEIGHT = 36;
const TOOLBAR_GAP = 8;
const VIEWPORT_MARGIN = 8;

const SIMPLE_BUTTONS = [
  { type: 'bold', label: 'B', title: 'Gras (Ctrl+B)', className: 'font-bold' },
  { type: 'italic', label: 'I', title: 'Italique (Ctrl+I)', className: 'italic' },
  { type: 'underline', label: 'U', title: 'Soulignement (Ctrl+U)', className: 'underline' },
  { type: 'strike', label: 'S', title: 'Barré', className: 'line-through' },
  { type: 'code', label: <CodeSimpleIcon width={15} height={15} />, title: 'Code (Ctrl+E)', className: '' },
];

export default function InlineToolbar({ rect, activeMarks, onToggleMark, onSetMark, onClearMarks, onPinChange, usedColors }) {
  const ref = useRef(null);
  const [pos, setPos] = useState({ top: 0, left: 0, flipped: false });
  const [openSubmenu, setOpenSubmenu] = useState(null);
  const [linkUrl, setLinkUrl] = useState('');
  const [linkNewTab, setLinkNewTab] = useState(false);

  useEffect(() => {
    onPinChange?.(openSubmenu !== null);
    return () => { onPinChange?.(false); };
  }, [openSubmenu, onPinChange]);

  // Sous-menus en mode clic : fermeture sur clic extérieur ou Escape.
  useEffect(() => {
    if (openSubmenu === null) return;
    function handleDocMouseDown(e) {
      if (ref.current && !ref.current.contains(e.target)) {
        setOpenSubmenu(null);
      }
    }
    function handleKeyDown(e) {
      if (e.key === 'Escape') setOpenSubmenu(null);
    }
    document.addEventListener('mousedown', handleDocMouseDown);
    document.addEventListener('keydown', handleKeyDown);
    return () => {
      document.removeEventListener('mousedown', handleDocMouseDown);
      document.removeEventListener('keydown', handleKeyDown);
    };
  }, [openSubmenu]);

  useLayoutEffect(() => {
    if (!rect || typeof window === 'undefined') return;
    const el = ref.current;
    if (!el) return;
    const w = el.offsetWidth || 280;
    const h = el.offsetHeight || TOOLBAR_HEIGHT;
    const container = el.offsetParent;
    const containerW = container?.clientWidth ?? Infinity;
    const containerVPTop = container?.getBoundingClientRect?.().top ?? 0;
    const selectionVPTop = containerVPTop + rect.top;
    const spaceAbove = selectionVPTop - VIEWPORT_MARGIN;
    const flipBelow = spaceAbove < h + TOOLBAR_GAP;
    let top = flipBelow ? rect.bottom + TOOLBAR_GAP : rect.top - h - TOOLBAR_GAP;
    let left = rect.left + rect.width / 2 - w / 2;
    if (left + w + VIEWPORT_MARGIN > containerW) left = containerW - w - VIEWPORT_MARGIN;
    if (left < VIEWPORT_MARGIN) left = VIEWPORT_MARGIN;
    if (top < 0) top = 0;
    setPos({ top, left, flipped: flipBelow });
  }, [rect]);

  function toggleSubmenu(key) {
    setOpenSubmenu(prev => {
      if (prev === key) return null;
      if (key === 'link') {
        const link = activeMarks.find(m => m.type === 'link');
        setLinkUrl(link?.href ?? '');
        setLinkNewTab(link ? !!link.newTab : false);
      }
      return key;
    });
  }

  function closeSubmenu() {
    setOpenSubmenu(null);
  }

  function isActive(type, payloadKey) {
    if (!Array.isArray(activeMarks)) return false;
    if (payloadKey) return activeMarks.some(m => markKey(m) === payloadKey);
    return activeMarks.some(m => m.type === type);
  }

  function handleSimple(type) {
    onToggleMark?.({ type });
  }

  function handleColor(color) {
    onToggleMark?.({ type: 'color', color });
    closeSubmenu();
  }

  function handleHighlight(color) {
    onToggleMark?.({ type: 'highlight', color });
    closeSubmenu();
  }

  function handleLinkSubmit(e) {
    e?.preventDefault?.();
    if (!linkUrl) return;
    onSetMark?.({ type: 'link', href: linkUrl, newTab: linkNewTab });
    setLinkUrl('');
    closeSubmenu();
  }

  function handleLinkRemove() {
    const link = activeMarks.find(m => m.type === 'link');
    if (link) onToggleMark?.({ type: 'link', href: link.href, ...(link.newTab ? { newTab: true } : {}) });
    closeSubmenu();
  }

  return (
    <div
      ref={ref}
      data-inline-toolbar
      className={`absolute z-50 flex items-center gap-0.5 p-1 ${BOX_CLASS}`}
      style={{ top: pos.top, left: pos.left }}
    >
      {SIMPLE_BUTTONS.map(btn => (
        <button
          key={btn.type}
          type="button"
          title={btn.title}
          onMouseDown={(e) => e.preventDefault()}
          onClick={() => handleSimple(btn.type)}
          className={`${ICON_BTN_CLASS} ${btn.className} ${isActive(btn.type) ? ICON_BTN_ACTIVE_CLASS : ''}`}
        >
          {btn.label}
        </button>
      ))}

      <span className={SEPARATOR_VERTICAL_CLASS} aria-hidden />

      <SubmenuTrigger
        title="Couleur du texte"
        active={isActive('color')}
        open={openSubmenu === 'color'}
        flipUp={pos.flipped}
        onToggle={() => toggleSubmenu('color')}
        icon={<TextColorIcon width={16} height={16} />}
      >
        <ColorGrid
          mode="text"
          activeKey={activeMarks.find(m => m.type === 'color')?.color}
          usedColors={usedColors?.color}
          onPick={handleColor}
        />
      </SubmenuTrigger>

      <SubmenuTrigger
        title="Surlignage"
        active={isActive('highlight')}
        open={openSubmenu === 'highlight'}
        flipUp={pos.flipped}
        onToggle={() => toggleSubmenu('highlight')}
        icon={<HighlighterIcon width={16} height={16} />}
      >
        <ColorGrid
          mode="highlight"
          activeKey={activeMarks.find(m => m.type === 'highlight')?.color}
          usedColors={usedColors?.highlight}
          onPick={handleHighlight}
        />
      </SubmenuTrigger>

      <SubmenuTrigger
        title="Lien (Ctrl+K)"
        active={isActive('link')}
        open={openSubmenu === 'link'}
        flipUp={pos.flipped}
        onToggle={() => toggleSubmenu('link')}
        icon={<Link02Icon width={16} height={16} />}
      >
        <LinkForm
          url={linkUrl}
          newTab={linkNewTab}
          showRemove={isActive('link')}
          onUrlChange={setLinkUrl}
          onNewTabChange={setLinkNewTab}
          onSubmit={handleLinkSubmit}
          onRemove={handleLinkRemove}
        />
      </SubmenuTrigger>

      <span className={SEPARATOR_VERTICAL_CLASS} aria-hidden />

      <button
        type="button"
        title="Effacer le formatage"
        onMouseDown={(e) => e.preventDefault()}
        onClick={() => onClearMarks?.()}
        className={ICON_BTN_CLASS}
      >
        <TextClearIcon width={16} height={16} />
      </button>
    </div>
  );
}

// Wrapper click-to-open pour les boutons de la toolbar avec sous-menu. Le
// panneau reste ouvert tant qu'on n'a pas cliqué à l'extérieur ou appuyé
// sur Escape (logique gérée par le parent `InlineToolbar`).
function SubmenuTrigger({ title, active, open, flipUp, icon, children, onToggle }) {
  const panelPosition = flipUp ? 'bottom-full mb-1' : 'top-full mt-1';
  return (
    <div className="relative">
      <button
        type="button"
        title={title}
        onMouseDown={(e) => e.preventDefault()}
        onClick={onToggle}
        className={`h-7 px-1.5 flex items-center gap-0.5 rounded-lg text-[13px] leading-none text-neutral-500 dark:text-neutral-400 hover:bg-neutral-100 dark:hover:bg-white/5 hover:text-neutral-900 dark:hover:text-white transition-colors duration-[120ms] ease-out ${active || open ? ICON_BTN_ACTIVE_CLASS : ''}`}
      >
        {icon}
        <ArrowDown01Icon width={10} height={10} className="opacity-60" />
      </button>
      {open && (
        <div className={`absolute ${panelPosition} left-0 ${BOX_CLASS} p-1.5 z-50`}>
          {children}
        </div>
      )}
    </div>
  );
}

function LinkForm({ url, newTab, showRemove, onUrlChange, onNewTabChange, onSubmit, onRemove }) {
  return (
    <div className="flex flex-col gap-1.5">
      <div className="flex items-center gap-1">
        <input
          type="url"
          placeholder="https://..."
          value={url}
          onChange={(e) => onUrlChange(e.target.value)}
          onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); onSubmit(e); } }}
          className="w-56 px-2 py-1 text-sm rounded border border-neutral-200 dark:border-neutral-700 bg-white dark:bg-neutral-900 text-neutral-900 dark:text-white outline-none focus:border-blue-500"
        />
        <button
          type="button"
          onClick={onSubmit}
          className="px-2 py-1 text-xs rounded bg-blue-600 hover:bg-blue-700 text-white"
        >
          OK
        </button>
        {showRemove && (
          <button
            type="button"
            onClick={onRemove}
            title="Retirer le lien"
            className="px-2 py-1 text-xs rounded text-red-600 hover:bg-red-50 dark:hover:bg-red-900/30"
          >
            ✕
          </button>
        )}
      </div>
      <label className="flex items-center gap-2 text-xs text-neutral-700 dark:text-neutral-300 select-none cursor-pointer">
        <input
          type="checkbox"
          checked={newTab}
          onChange={(e) => onNewTabChange(e.target.checked)}
          className="cursor-pointer"
        />
        Ouvrir dans un nouvel onglet
      </label>
    </div>
  );
}

const USED_COLORS_LIMIT = 8;

function ColorGrid({ mode, activeKey, usedColors, onPick }) {
  const pickerRef = useRef(null);
  const used = Array.isArray(usedColors) ? usedColors.slice(0, USED_COLORS_LIMIT) : [];
  const isText = mode === 'text';

  function openCustomPicker() {
    pickerRef.current?.click();
  }

  function handleCustomChange(e) {
    const value = e.target.value;
    if (value) onPick(value);
  }

  return (
    <div className="flex items-center gap-1">
      {INLINE_COLOR_KEYS.map(key => {
        const palette = INLINE_COLORS[key];
        const tw = isText ? palette.text : palette.highlight;
        return (
          <button
            key={key}
            type="button"
            title={key}
            onMouseDown={(e) => e.preventDefault()}
            onClick={() => onPick(key)}
            className={`w-6 h-6 flex items-center justify-center rounded ${tw} ${activeKey === key ? 'ring-2 ring-blue-500' : ''}`}
          >
            <span className={isText ? 'font-semibold' : ''}>A</span>
          </button>
        );
      })}
      {used.length > 0 && (
        <span className="mx-1 w-px h-5 bg-neutral-200 dark:bg-neutral-700" aria-hidden />
      )}
      {used.map(value => (
        <button
          key={value}
          type="button"
          title={`Utilisée : ${value}`}
          onMouseDown={(e) => e.preventDefault()}
          onClick={() => onPick(value)}
          style={isText ? { color: value } : { backgroundColor: value }}
          className={`w-6 h-6 flex items-center justify-center rounded ${activeKey === value ? 'ring-2 ring-blue-500' : ''}`}
        >
          <span className={isText ? 'font-semibold' : ''}>A</span>
        </button>
      ))}
      <span className="mx-1 w-px h-5 bg-neutral-200 dark:bg-neutral-700" aria-hidden />
      <button
        type="button"
        title="Couleur personnalisée"
        onMouseDown={(e) => e.preventDefault()}
        onClick={openCustomPicker}
        className="w-6 h-6 flex items-center justify-center rounded border border-dashed border-neutral-300 dark:border-neutral-600 text-neutral-500 dark:text-neutral-400 hover:bg-neutral-100 dark:hover:bg-neutral-800"
      >
        <span aria-hidden>+</span>
      </button>
      <input
        ref={pickerRef}
        type="color"
        onChange={handleCustomChange}
        onMouseDown={(e) => e.stopPropagation()}
        className="absolute opacity-0 pointer-events-none w-0 h-0"
        tabIndex={-1}
        aria-hidden
      />
    </div>
  );
}
