"use client";
import { useEffect, useMemo, useRef, useState } from 'react';
import Markdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import { isHtmlArtifact, wrapArtifactContent } from './artifact-utils';
import SpaceShareModal from './space-share-modal.jsx';

function SpaceChip({ space, active, count, onActivate, onRename, onDelete, onShare, isEmpty, canDelete, onMoveArtifactHere, dragOverSpaceId, setDragOverSpaceId, pointerDropSpaceId }) {
  const [editing, setEditing] = useState(false);
  const [draft, setDraft] = useState(space.name);
  const [menuOpen, setMenuOpen] = useState(false);
  const menuRef = useRef(null);
  const inputRef = useRef(null);

  useEffect(() => { setDraft(space.name); }, [space.name]);
  useEffect(() => {
    if (!menuOpen) return;
    function onDocPointer(e) {
      if (!menuRef.current?.contains(e.target)) setMenuOpen(false);
    }
    document.addEventListener('pointerdown', onDocPointer);
    return () => document.removeEventListener('pointerdown', onDocPointer);
  }, [menuOpen]);
  useEffect(() => {
    if (editing) {
      inputRef.current?.focus();
      inputRef.current?.select();
    }
  }, [editing]);

  function commitRename() {
    setEditing(false);
    const trimmed = draft.trim();
    if (trimmed && trimmed !== space.name) onRename(space.id, trimmed);
    else setDraft(space.name);
  }

  return (
    <div
      data-space-id={space.id}
      className={
        'space-chip'
        + (active ? ' is-active' : '')
        + ((dragOverSpaceId === space.id || pointerDropSpaceId === space.id) ? ' is-drop-target' : '')
      }
      onClick={() => { if (!editing) onActivate(space.id); }}
      onDoubleClick={e => { e.stopPropagation(); setEditing(true); }}
      onContextMenu={e => { e.preventDefault(); setMenuOpen(true); }}
      onDragOver={e => { e.preventDefault(); setDragOverSpaceId(space.id); }}
      onDragLeave={() => setDragOverSpaceId(prev => prev === space.id ? null : prev)}
      onDrop={e => {
        e.preventDefault();
        const artifactId = e.dataTransfer.getData('text/x-artifact-id');
        if (artifactId) onMoveArtifactHere(artifactId, space.id);
        setDragOverSpaceId(null);
      }}
      title={editing ? '' : 'Click to switch · Double-click to rename · Right-click for more'}
    >
      {editing ? (
        <>
          <input
            ref={inputRef}
            className="space-chip-input"
            value={draft}
            onChange={e => setDraft(e.target.value)}
            onBlur={commitRename}
            onKeyDown={e => {
              if (e.key === 'Enter') commitRename();
              else if (e.key === 'Escape') { setEditing(false); setDraft(space.name); }
            }}
            maxLength={32}
          />
          {isEmpty && canDelete && (
            <button
              type="button"
              className="space-chip-action space-chip-action--delete"
              onMouseDown={e => e.preventDefault()}
              onClick={e => { e.stopPropagation(); onDelete(space.id); }}
              aria-label={`Delete ${space.name}`}
              title="Delete empty space"
              tabIndex={-1}
            >
              <svg width="10" height="10" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" aria-hidden="true">
                <line x1="3.5" y1="3.5" x2="12.5" y2="12.5"/>
                <line x1="12.5" y1="3.5" x2="3.5" y2="12.5"/>
              </svg>
            </button>
          )}
        </>
      ) : (
        <>
          <span className="space-chip-name">{space.name}</span>
          {count > 0 && <span className="space-chip-count">{count}</span>}
        </>
      )}
      {menuOpen && (
        <div className="space-chip-menu" ref={menuRef} onClick={e => e.stopPropagation()}>
          <button type="button" onClick={() => { setMenuOpen(false); setEditing(true); }}>Rename</button>
          <button type="button" onClick={() => { setMenuOpen(false); onShare(space.id); }}>Share</button>
          <button
            type="button"
            disabled={!canDelete || !isEmpty}
            onClick={() => { setMenuOpen(false); if (canDelete && isEmpty) onDelete(space.id); }}
            title={!isEmpty ? 'Move or delete its artifacts first' : (canDelete ? 'Delete this empty space' : 'Cannot delete the last space')}
          >
            Delete{!isEmpty ? ' (not empty)' : ''}
          </button>
        </div>
      )}
    </div>
  );
}

function DockItem({ artifact, spaces, activeSpaceId, hoveredDockId, setHoveredDockId, onRestore, onMove }) {
  const isHtml = isHtmlArtifact(artifact.kind);
  const [menuOpen, setMenuOpen] = useState(false);
  const menuRef = useRef(null);

  useEffect(() => {
    if (!menuOpen) return;
    function onDocPointer(e) {
      if (!menuRef.current?.contains(e.target)) setMenuOpen(false);
    }
    document.addEventListener('pointerdown', onDocPointer);
    return () => document.removeEventListener('pointerdown', onDocPointer);
  }, [menuOpen]);

  const otherSpaces = spaces.filter(s => s.id !== activeSpaceId);

  return (
    <div
      className="dock-item"
      onMouseEnter={() => setHoveredDockId(artifact.id)}
      onMouseLeave={() => setHoveredDockId(prev => (prev === artifact.id ? null : prev))}
      onContextMenu={e => { e.preventDefault(); setMenuOpen(true); }}
      draggable
      onDragStart={e => {
        e.dataTransfer.setData('text/x-artifact-id', artifact.id);
        e.dataTransfer.effectAllowed = 'move';
      }}
    >
      <button
        type="button"
        className="dock-card"
        onClick={() => onRestore(artifact.id)}
        aria-label={`Restore: ${artifact.title}`}
        title={artifact.title || 'Artifact'}
      >
        <div className="dock-thumb">
          {artifact.content ? (
            isHtml ? (
              <iframe
                srcDoc={wrapArtifactContent(artifact.content)}
                sandbox="allow-same-origin"
                title={`Thumbnail: ${artifact.title}`}
                tabIndex={-1}
                aria-hidden="true"
                loading="lazy"
              />
            ) : (
              <div className="win-md"><Markdown remarkPlugins={[remarkGfm]}>{artifact.content}</Markdown></div>
            )
          ) : (
            <div className="dock-thumb-empty">{artifact.kind || 'doc'}</div>
          )}
        </div>
      </button>
      {hoveredDockId === artifact.id && !menuOpen && (
        <div className="dock-preview" role="tooltip">
          <div className="dock-preview-title">
            <span className={'artifact-kind-badge ' + (artifact.kind || 'text')}>{artifact.kind}</span>
            <b>{artifact.title || 'Artifact'}</b>
          </div>
          <div className={'dock-preview-body' + (isHtml ? ' is-html' : ' is-md')}>
            {isHtml ? (
              <iframe
                srcDoc={wrapArtifactContent(artifact.content)}
                sandbox="allow-scripts allow-same-origin"
                title={`Preview: ${artifact.title}`}
                tabIndex={-1}
                aria-hidden="true"
              />
            ) : (
              <div className="win-md"><Markdown remarkPlugins={[remarkGfm]}>{artifact.content || ''}</Markdown></div>
            )}
          </div>
        </div>
      )}
      {menuOpen && (
        <div className="dock-item-menu" ref={menuRef} onClick={e => e.stopPropagation()}>
          <div className="dock-item-menu-label">Move to space</div>
          {otherSpaces.length === 0 ? (
            <div className="dock-item-menu-empty">No other spaces</div>
          ) : (
            otherSpaces.map(s => (
              <button
                key={s.id}
                type="button"
                onClick={() => { onMove(artifact.id, s.id); setMenuOpen(false); }}
              >
                {s.name}
              </button>
            ))
          )}
          <div className="dock-item-menu-divider" />
          <button type="button" onClick={() => { onRestore(artifact.id); setMenuOpen(false); }}>Restore</button>
        </div>
      )}
    </div>
  );
}

export default function ArtifactDock({
  spaces,
  activeSpaceId,
  setActiveSpaceId,
  createSpace,
  renameSpace,
  deleteSpace,
  moveArtifactToSpace,
  artifacts,
  dockedArtifacts,
  minimizedIds,
  hoveredDockId,
  setHoveredDockId,
  toggleMinimize,
  pointerDropSpaceId,
}) {
  const [dragOverSpaceId, setDragOverSpaceId] = useState(null);
  const [shareSpaceId, setShareSpaceId] = useState(null);

  // Per-space artifact membership derived from artifact.space_id — server is
  // the single source of truth. Legacy NULL space_id rows collapse to 'default'.
  const idsBySpace = useMemo(() => {
    const map = new Map();
    for (const s of spaces) map.set(s.id, []);
    for (const a of artifacts || []) {
      const sid = a.space_id || 'default';
      if (map.has(sid)) map.get(sid).push(a.id);
    }
    return map;
  }, [spaces, artifacts]);

  function countFor(space) {
    const ids = idsBySpace.get(space.id) || [];
    return ids.filter((id) => !minimizedIds[id]).length;
  }

  function isEmpty(space) {
    return (idsBySpace.get(space.id) || []).length === 0;
  }

  function onMoveArtifactToSpace(artifactId, targetSpaceId) {
    moveArtifactToSpace(artifactId, targetSpaceId);
    // After moving, the artifact stops being visible in the active space. Keep its minimized
    // flag as-is so it ends up in the destination space's dock (if minimized) or visible there.
  }

  return (
    <div className="artifact-dock" role="toolbar" aria-label="Spaces and minimized artifacts">
      <div className="dock-spaces">
        {spaces.map(space => (
          <SpaceChip
            key={space.id}
            space={space}
            active={space.id === activeSpaceId}
            count={countFor(space)}
            isEmpty={isEmpty(space)}
            onActivate={setActiveSpaceId}
            onRename={renameSpace}
            onDelete={deleteSpace}
            onShare={setShareSpaceId}
            canDelete={spaces.length > 1}
            onMoveArtifactHere={onMoveArtifactToSpace}
            dragOverSpaceId={dragOverSpaceId}
            setDragOverSpaceId={setDragOverSpaceId}
            pointerDropSpaceId={pointerDropSpaceId}
          />
        ))}
        <button
          type="button"
          className="space-add"
          onClick={() => createSpace()}
          aria-label="Create new space"
          title="New space"
        >
          <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round">
            <line x1="12" y1="5" x2="12" y2="19"/>
            <line x1="5" y1="12" x2="19" y2="12"/>
          </svg>
        </button>
      </div>
      {dockedArtifacts.length > 0 && (
        <>
          <div className="dock-divider" aria-hidden="true" />
          <div className="dock-items">
            {dockedArtifacts.map(a => (
              <DockItem
                key={a.id}
                artifact={a}
                spaces={spaces}
                activeSpaceId={activeSpaceId}
                hoveredDockId={hoveredDockId}
                setHoveredDockId={setHoveredDockId}
                onRestore={toggleMinimize}
                onMove={onMoveArtifactToSpace}
              />
            ))}
          </div>
        </>
      )}
      {shareSpaceId ? (
        <SpaceShareModal
          spaceId={shareSpaceId}
          spaceName={(spaces.find((s) => s.id === shareSpaceId) || {}).name || 'Space'}
          onClose={() => setShareSpaceId(null)}
        />
      ) : null}
    </div>
  );
}
