'use client';

import dynamic from 'next/dynamic';
import { useEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import PreviewBody from './preview-body.jsx';

const SharePanel = dynamic(() => import('./share-panel.jsx'));

function when(value) {
  if (!value) return '';
  try {
    return new Intl.DateTimeFormat('en', {
      month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit',
    }).format(new Date(value));
  } catch { return value; }
}

function itemName(item) {
  return item.source_type === 'artifact' ? (item.title || item.path || item.id) : item.name;
}

function itemKindLabel(item) {
  if (item.source_type === 'artifact') return item.kind || 'artifact';
  if (item.local_only) return 'local';
  return item.kind || 'file';
}

function itemAuthorLabel(item) {
  if (item.source_type === 'artifact') {
    const id = item.agent_id || '';
    if (!id) return 'Agent';
    if (id === 'main-orchestrator') return 'Main agent';
    if (id === 'ops-agent') return 'Caretaker';
    return id;
  }
  return 'You';
}

function downloadInfo(item) {
  const base = (item.source_type === 'artifact' ? (item.title || 'artifact') : (item.name || 'document'))
    .replace(/[\\/:*?"<>|]+/g, '-').trim() || 'download';
  if (item.render_kind === 'html') return { ext: 'html', mime: 'text/html;charset=utf-8', name: base };
  if (item.render_kind === 'markdown') return { ext: 'md', mime: 'text/markdown;charset=utf-8', name: base };
  return { ext: 'txt', mime: 'text/plain;charset=utf-8', name: base };
}

function downloadItem(item) {
  if (!item || !item.body) return;
  const info = downloadInfo(item);
  const filename = /\.[a-z0-9]+$/i.test(info.name) ? info.name : `${info.name}.${info.ext}`;
  const blob = new Blob([item.body], { type: info.mime });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  document.body.appendChild(a);
  a.click();
  a.remove();
  setTimeout(() => URL.revokeObjectURL(url), 1000);
}

// ---------------------------------------------------------------------------
// FloatingArtifactWindow — drag, resize, double-click expand, traffic-light dots.
// ---------------------------------------------------------------------------

const MIN_W = 320;
const MIN_H = 220;
const PAD = 8;
const DEFAULT_W = 760;
const DEFAULT_H = 580;

function initialFloatLayout() {
  if (typeof window === 'undefined') return { x: 80, y: 80, width: DEFAULT_W, height: DEFAULT_H };
  const vw = window.innerWidth;
  const vh = window.innerHeight;
  const width = Math.min(DEFAULT_W, vw - PAD * 2);
  const height = Math.min(DEFAULT_H, vh - PAD * 2);
  return {
    x: Math.max(PAD, Math.round((vw - width) / 2)),
    y: Math.max(PAD, Math.round((vh - height) / 2 - 24)),
    width,
    height,
  };
}

export default function FloatingArtifactWindow({ item, onClose, isProtected = false, onToggleProtect, onDelete, deleting = false, folders = [], rootFolderId = null, onMove, moving = false, protectError = null, spaces = [], onBookmarkToSpace, bookmarking = false }) {
  const titleId = 'project-float-title';
  const [layout, setLayout] = useState(initialFloatLayout);
  const [expanded, setExpanded] = useState(false);
  const [dragging, setDragging] = useState(false);
  const [resizing, setResizing] = useState(false);
  const [sharePanelOpen, setSharePanelOpen] = useState(false);
  const [confirmDelete, setConfirmDelete] = useState(false);
  const expandedRef = useRef(false);
  expandedRef.current = expanded;

  useEffect(() => {
    if (!item) return undefined;
    setLayout(initialFloatLayout());
    setExpanded(false);
    setConfirmDelete(false);
    const onKey = (e) => {
      if (e.key === 'Escape') {
        if (expandedRef.current) setExpanded(false);
        else onClose();
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [item, onClose]);

  useEffect(() => {
    function onResize() {
      setLayout((prev) => {
        const vw = window.innerWidth;
        const vh = window.innerHeight;
        const width = Math.min(prev.width, vw - PAD * 2);
        const height = Math.min(prev.height, vh - PAD * 2);
        const x = Math.min(Math.max(PAD, prev.x), vw - width - PAD);
        const y = Math.min(Math.max(PAD, prev.y), vh - height - PAD);
        return { x, y, width, height };
      });
    }
    window.addEventListener('resize', onResize);
    return () => window.removeEventListener('resize', onResize);
  }, []);

  const toggleExpanded = () => setExpanded((v) => !v);

  function startDrag(e) {
    if (expanded) return;
    if (e.target.closest('button, i, .winbar-dl, .winbar-protect, .winbar-share, .winbar-space, .artifact-kind-badge')) return;
    e.preventDefault();
    const startX = e.clientX;
    const startY = e.clientY;
    const startLeft = layout.x;
    const startTop = layout.y;
    setDragging(true);
    e.currentTarget.setPointerCapture?.(e.pointerId);
    const target = e.currentTarget;
    document.body.style.userSelect = 'none';
    const onMove = (mv) => {
      mv.preventDefault();
      const vw = window.innerWidth;
      const vh = window.innerHeight;
      const dx = mv.clientX - startX;
      const dy = mv.clientY - startY;
      const x = Math.min(Math.max(PAD, startLeft + dx), vw - layout.width - PAD);
      const y = Math.min(Math.max(PAD, startTop + dy), vh - layout.height - PAD);
      setLayout((prev) => ({ ...prev, x, y }));
    };
    const onUp = (up) => {
      target.removeEventListener('pointermove', onMove);
      target.removeEventListener('pointerup', onUp);
      target.removeEventListener('pointercancel', onUp);
      target.releasePointerCapture?.(up.pointerId);
      document.body.style.userSelect = '';
      setDragging(false);
    };
    target.addEventListener('pointermove', onMove);
    target.addEventListener('pointerup', onUp);
    target.addEventListener('pointercancel', onUp);
  }

  function startResize(e, dir) {
    if (expanded) return;
    e.preventDefault();
    e.stopPropagation();
    const startX = e.clientX;
    const startY = e.clientY;
    const start = { ...layout };
    setResizing(true);
    e.currentTarget.setPointerCapture?.(e.pointerId);
    const target = e.currentTarget;
    const cursorByDir = {
      n: 'ns-resize', s: 'ns-resize', e: 'ew-resize', w: 'ew-resize',
      ne: 'nesw-resize', sw: 'nesw-resize', nw: 'nwse-resize', se: 'nwse-resize',
    };
    document.body.style.userSelect = 'none';
    document.body.style.cursor = cursorByDir[dir] || 'nwse-resize';
    const onMove = (mv) => {
      mv.preventDefault();
      const vw = window.innerWidth;
      const vh = window.innerHeight;
      let dx = mv.clientX - startX;
      let dy = mv.clientY - startY;
      let nx = start.x;
      let ny = start.y;
      let nw = start.width;
      let nh = start.height;
      if (dir.includes('w')) {
        if (start.width - dx < MIN_W) dx = start.width - MIN_W;
        if (start.x + dx < PAD) dx = PAD - start.x;
        nx = start.x + dx;
        nw = start.width - dx;
      }
      if (dir.includes('e')) {
        if (start.width + dx < MIN_W) dx = MIN_W - start.width;
        if (start.x + start.width + dx > vw - PAD) dx = vw - PAD - start.x - start.width;
        nw = start.width + dx;
      }
      if (dir.includes('n')) {
        if (start.height - dy < MIN_H) dy = start.height - MIN_H;
        if (start.y + dy < PAD) dy = PAD - start.y;
        ny = start.y + dy;
        nh = start.height - dy;
      }
      if (dir.includes('s')) {
        if (start.height + dy < MIN_H) dy = MIN_H - start.height;
        if (start.y + start.height + dy > vh - PAD) dy = vh - PAD - start.y - start.height;
        nh = start.height + dy;
      }
      setLayout({ x: nx, y: ny, width: nw, height: nh });
    };
    const onUp = (up) => {
      target.removeEventListener('pointermove', onMove);
      target.removeEventListener('pointerup', onUp);
      target.removeEventListener('pointercancel', onUp);
      target.releasePointerCapture?.(up.pointerId);
      document.body.style.userSelect = '';
      document.body.style.cursor = '';
      setResizing(false);
    };
    target.addEventListener('pointermove', onMove);
    target.addEventListener('pointerup', onUp);
    target.addEventListener('pointercancel', onUp);
  }

  if (!item) return null;
  if (typeof document === 'undefined') return null;

  const title = itemName(item);
  const isLocal = item.source_type === 'file' && item.local_only;
  const canDownload = Boolean(item.body) && !isLocal;
  const kind = itemKindLabel(item);
  const author = itemAuthorLabel(item);
  const ts = item.updated_at || item.created_at;

  const wrapStyle = expanded
    ? { transform: 'translate3d(0,0,0)', width: '100vw', height: '100vh' }
    : { transform: `translate3d(${layout.x}px, ${layout.y}px, 0)`, width: layout.width, height: layout.height };

  return createPortal(
    <div
      className={`project-float-root${expanded ? ' is-expanded' : ''}`}
      role="presentation"
      aria-hidden={!item ? 'true' : undefined}
    >
      <div
        className={`artifact-window-wrap project-float-wrap${expanded ? ' is-expanded' : ''}`}
        data-dragging={dragging ? 'true' : 'false'}
        data-resizing={resizing ? 'true' : 'false'}
        style={wrapStyle}
      >
        <div className="window artifact-window project-float-window" role="dialog" aria-modal="true" aria-labelledby={titleId}>
          <div
            className="winbar"
            onPointerDown={confirmDelete ? undefined : startDrag}
            onDoubleClick={(e) => {
              if (e.target.closest('button, i, .winbar-dl, .winbar-protect, .winbar-share, .winbar-space, .winbar-delete, .confirm-label, .confirm-cancel, .confirm-delete, .artifact-kind-badge')) return;
              if (confirmDelete) return;
              toggleExpanded();
            }}
            title={expanded ? 'Double-click to exit full screen' : 'Drag to move · Double-click to expand'}
          >
            {confirmDelete ? (
              <>
                <span className="confirm-label">Delete permanently?</span>
                <button
                  type="button"
                  className="confirm-cancel"
                  onPointerDown={(e) => e.stopPropagation()}
                  onClick={() => setConfirmDelete(false)}
                  disabled={deleting}
                >
                  Cancel
                </button>
                <button
                  type="button"
                  className="confirm-delete"
                  onPointerDown={(e) => e.stopPropagation()}
                  onClick={() => onDelete?.()}
                  disabled={deleting}
                >
                  {deleting ? 'Deleting…' : 'Delete'}
                </button>
              </>
            ) : (
              <>
            <i
              className="dot-close"
              role="button"
              tabIndex={0}
              onPointerDown={(e) => e.stopPropagation()}
              onClick={onClose}
              onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onClose(); } }}
              aria-label="Close"
              title="Close"
            />
            <i
              className="dot-zoom"
              role="button"
              tabIndex={0}
              onPointerDown={(e) => e.stopPropagation()}
              onClick={toggleExpanded}
              onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggleExpanded(); } }}
              aria-label={expanded ? 'Exit full screen' : 'Expand to full screen'}
              aria-pressed={expanded}
              title={expanded ? 'Exit full screen' : 'Expand'}
            />
            <b id={titleId} title={title}>{title}</b>
            <span className={'artifact-kind-badge ' + (kind || 'text')}>{kind}</span>
            <span className="winbar-meta">
              <span>{author}</span>
              {ts ? <>
                <span aria-hidden="true"> · </span>
                <time dateTime={ts}>{when(ts)}</time>
              </> : null}
            </span>
            {protectError ? (
              <span className="winbar-protect-error" role="alert">{protectError}</span>
            ) : null}
            <button
              type="button"
              className={`winbar-protect${isProtected ? ' on' : ''}`}
              onPointerDown={(e) => e.stopPropagation()}
              onClick={() => onToggleProtect?.()}
              aria-pressed={isProtected}
              aria-label={isProtected ? 'Remove protection' : 'Protect with passphrase'}
              title={isProtected ? 'Protected — click to remove' : 'Protect with passphrase'}
            >
              {isProtected ? (
                <svg width="11" height="11" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                  <rect x="3" y="7" width="10" height="7" rx="1.5" />
                  <path d="M5 7V5a3 3 0 0 1 6 0v2" />
                </svg>
              ) : (
                <svg width="11" height="11" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                  <rect x="3" y="7" width="10" height="7" rx="1.5" />
                  <path d="M5 7V5a3 3 0 0 1 6 0" />
                </svg>
              )}
            </button>
            <label
              className="winbar-move"
              onPointerDown={(e) => e.stopPropagation()}
              title="Move to folder"
            >
              <svg width="11" height="11" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                <path d="M2 5a1 1 0 0 1 1-1h3.5l1.5 1.5H13a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V5Z" />
              </svg>
              <select
                aria-label="Move to folder"
                disabled={moving}
                value={item?.folder_id || rootFolderId || ''}
                onChange={(e) => {
                  const v = e.target.value;
                  onMove?.(v === rootFolderId ? rootFolderId : v || null);
                }}
              >
                {rootFolderId ? <option value={rootFolderId}>Library (root)</option> : <option value="">Library (root)</option>}
                {folders
                  .filter((f) => f.parent_id != null)
                  .map((f) => (
                    <option key={f.id} value={f.id}>{f.path.replace(/^\/|\/$/g, '').split('/').slice(1).join(' / ') || f.name}</option>
                  ))}
              </select>
            </label>
            {item.source_type === 'artifact' && spaces.length > 0 ? (
              <label
                className="winbar-space"
                onPointerDown={(e) => e.stopPropagation()}
                title="Bookmark to a dashboard space"
              >
                <svg width="11" height="11" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                  <path d="M4 2h8a1 1 0 0 1 1 1v11l-5-3-5 3V3a1 1 0 0 1 1-1Z" />
                </svg>
                <select
                  aria-label="Bookmark to dashboard space"
                  disabled={bookmarking}
                  value={item?.space_id || ''}
                  onChange={(e) => {
                    const v = e.target.value;
                    if (v) onBookmarkToSpace?.(v);
                  }}
                >
                  <option value="" disabled>Pin to space…</option>
                  {spaces.map((s) => (
                    <option key={s.id} value={s.id}>{s.name}</option>
                  ))}
                </select>
              </label>
            ) : null}
            <button
              type="button"
              className="winbar-share"
              onPointerDown={(e) => e.stopPropagation()}
              onClick={() => setSharePanelOpen(true)}
              aria-label="Share artifact"
              title="Share"
            >
              <svg width="11" height="11" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                <circle cx="12" cy="3" r="1.5" /><circle cx="4" cy="8" r="1.5" /><circle cx="12" cy="13" r="1.5" />
                <path d="M10.5 3.9L5.5 7.1M5.5 8.9l5 3.2" />
              </svg>
            </button>
            {canDownload ? (
              <button
                type="button"
                className="winbar-dl"
                onPointerDown={(e) => e.stopPropagation()}
                onClick={() => downloadItem(item)}
                aria-label={`Download ${title}`}
                title="Download"
              >
                <svg width="11" height="11" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                  <path d="M8 2v9M4 7l4 4 4-4" />
                  <line x1="2" y1="14" x2="14" y2="14" />
                </svg>
              </button>
            ) : null}
            <button
              type="button"
              className="winbar-delete"
              onPointerDown={(e) => e.stopPropagation()}
              onClick={() => setConfirmDelete(true)}
              aria-label={`Delete ${title}`}
              title="Delete"
            >
              <svg width="11" height="11" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                <path d="M3 4h10M6.5 4V2.5h3V4M5 4l.7 9a1.5 1.5 0 0 0 1.5 1.4h1.6a1.5 1.5 0 0 0 1.5-1.4L11 4" />
              </svg>
            </button>
              </>
            )}
          </div>
          <div className="win-content project-float-body">
            <PreviewBody item={item} />
          </div>
        </div>
        {!expanded ? ['nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w'].map((d) => (
          <div
            key={d}
            className={`resize-edge resize-${d}`}
            onPointerDown={(e) => startResize(e, d)}
          />
        )) : null}
      </div>
      {sharePanelOpen && (
        <SharePanel item={item} onClose={() => setSharePanelOpen(false)} />
      )}
    </div>,
    document.body,
  );
}
