'use client';

import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import Markdown from 'react-markdown';
import remarkGfm from 'remark-gfm';

const HTML_KINDS = new Set(['html', 'ui', 'document', 'mines_investor_presentation', 'mines_project_package']);
const MIN_W = 280;
const MIN_H = 190;
const PAD = 14;

function isHtmlArtifact(kind) {
  return HTML_KINDS.has(String(kind || '').toLowerCase());
}

function clamp(n, min, max) {
  return Math.max(min, Math.min(max, n));
}

function defaultLayoutFor(index, count, boardSize) {
  const width = boardSize.width || 1100;
  const height = boardSize.height || 680;
  const columns = width > 1180 && count > 1 ? 2 : 1;
  const cardW = clamp(columns === 2 ? Math.floor((width - 56) / 2) : Math.floor(width - 36), MIN_W, 620);
  const cardH = clamp(Math.floor(height * 0.58), 300, 520);
  const col = index % columns;
  const row = Math.floor(index / columns);
  return {
    x: PAD + col * (cardW + 20),
    y: PAD + row * 40,
    width: cardW,
    height: cardH,
  };
}

function readArtifactLayout(a) {
  const layout = a?.public_layout || a?.layout || a?.position || null;
  if (!layout || typeof layout !== 'object') return null;
  const x = Number(layout.x);
  const y = Number(layout.y);
  const width = Number(layout.width ?? layout.w);
  const height = Number(layout.height ?? layout.h);
  if (![x, y, width, height].every(Number.isFinite)) return null;
  return {
    x: Math.max(PAD, x),
    y: Math.max(PAD, y),
    width: Math.max(MIN_W, width),
    height: Math.max(MIN_H, height),
  };
}

function expiryText(link) {
  if (!link?.expires_at) return null;
  const diff = new Date(link.expires_at).getTime() - Date.now();
  const days = diff <= 0 ? 0 : Math.ceil(diff / 86400000);
  if (days === 0) return 'Expires today';
  if (days === 1) return 'Expires tomorrow';
  return `Expires in ${days} days`;
}

function PublicArtifactBody({ artifact, dragging, resizing }) {
  const kind = String(artifact.kind || '').toLowerCase();
  const content = artifact.content || artifact.source_md || '';
  if (isHtmlArtifact(kind)) {
    return (
      <>
        {(dragging || resizing) && <div className={dragging ? 'public-drag-blocker' : 'public-resize-blocker'} />}
        <iframe
          title={artifact.title || 'Artifact'}
          srcDoc={content}
          sandbox="allow-scripts allow-same-origin"
        />
      </>
    );
  }
  if (kind === 'json') {
    let formatted = content;
    try { formatted = JSON.stringify(JSON.parse(content), null, 2); } catch {}
    return <pre className="public-win-code"><code>{formatted}</code></pre>;
  }
  return <div className="public-win-md"><Markdown remarkPlugins={[remarkGfm]}>{content}</Markdown></div>;
}

export default function PublicSpaceCanvas({ token, space, artifacts = [], link = null }) {
  const boardRef = useRef(null);
  const nextZRef = useRef(30);
  const [boardSize, setBoardSize] = useState({ width: 0, height: 0 });
  const [layoutMode, setLayoutMode] = useState('auto');
  const [positions, setPositions] = useState({});
  const [sizes, setSizes] = useState({});
  const [zMap, setZMap] = useState({});
  const [draggingId, setDraggingId] = useState(null);
  const [resizingId, setResizingId] = useState(null);
  const [frontId, setFrontId] = useState(null);
  const [hydrated, setHydrated] = useState(false);

  const safeArtifacts = useMemo(
    () => (Array.isArray(artifacts) ? artifacts.filter((a) => a && a.id && (a.content || a.source_md)) : []),
    [artifacts]
  );

  const ownerPublishedLayout = useMemo(() => {
    const next = {};
    safeArtifacts.forEach((a, idx) => {
      next[a.id] = readArtifactLayout(a) || defaultLayoutFor(idx, Math.max(1, safeArtifacts.length), boardSize);
    });
    return next;
  }, [safeArtifacts, boardSize]);

  const localStorageKey = `madarx:public-space-layout:v1:${token}`;

  const applyOwnerLayout = useCallback(() => {
    const nextPositions = {};
    const nextSizes = {};
    Object.entries(ownerPublishedLayout).forEach(([id, L]) => {
      nextPositions[id] = { x: L.x, y: L.y };
      nextSizes[id] = { width: L.width, height: L.height };
    });
    setPositions(nextPositions);
    setSizes(nextSizes);
    setZMap({});
    nextZRef.current = 30;
    setFrontId(safeArtifacts[0]?.id || null);
  }, [ownerPublishedLayout, safeArtifacts]);

  function resetPublicLayout() {
    setLayoutMode('auto');
    applyOwnerLayout();
    try { localStorage.removeItem(localStorageKey); } catch {}
  }

  function getLayout(a, idx) {
    const fallback = ownerPublishedLayout[a.id] || defaultLayoutFor(idx, Math.max(1, safeArtifacts.length), boardSize);
    return {
      x: positions[a.id]?.x ?? fallback.x,
      y: positions[a.id]?.y ?? fallback.y,
      width: sizes[a.id]?.width ?? fallback.width,
      height: sizes[a.id]?.height ?? fallback.height,
    };
  }

  function bringToFront(id) {
    nextZRef.current += 1;
    const z = nextZRef.current;
    setFrontId(id);
    setZMap((prev) => ({ ...prev, [id]: z }));
  }

  function startDrag(e, id) {
    if (e.target.closest('button, .public-kind-badge')) return;
    e.preventDefault();
    const wrap = e.currentTarget.closest('.public-artifact-window-wrap');
    const board = boardRef.current;
    if (!wrap || !board) return;
    e.currentTarget.setPointerCapture?.(e.pointerId);
    setLayoutMode('manual');
    setDraggingId(id);
    bringToFront(id);
    const boardRect = board.getBoundingClientRect();
    const wrapRect = wrap.getBoundingClientRect();
    const startLeft = wrapRect.left - boardRect.left + board.scrollLeft;
    const startTop = wrapRect.top - boardRect.top + board.scrollTop;
    const grabX = e.clientX - boardRect.left + board.scrollLeft - startLeft;
    const grabY = e.clientY - boardRect.top + board.scrollTop - startTop;
    const target = e.currentTarget;
    document.body.style.userSelect = 'none';
    function onMove(mv) {
      mv.preventDefault();
      const rect = board.getBoundingClientRect();
      setPositions((prev) => ({
        ...prev,
        [id]: {
          x: Math.max(PAD, mv.clientX - rect.left + board.scrollLeft - grabX),
          y: Math.max(PAD, mv.clientY - rect.top + board.scrollTop - grabY),
        },
      }));
    }
    function onUp(up) {
      target.removeEventListener('pointermove', onMove);
      target.removeEventListener('pointerup', onUp);
      target.removeEventListener('pointercancel', onUp);
      target.releasePointerCapture?.(up.pointerId);
      document.body.style.userSelect = '';
      setDraggingId(null);
    }
    target.addEventListener('pointermove', onMove);
    target.addEventListener('pointerup', onUp);
    target.addEventListener('pointercancel', onUp);
  }

  function startResize(e, id, dir) {
    e.preventDefault();
    e.stopPropagation();
    const wrap = e.currentTarget.closest('.public-artifact-window-wrap');
    const board = boardRef.current;
    if (!wrap || !board) return;
    e.currentTarget.setPointerCapture?.(e.pointerId);
    setLayoutMode('manual');
    setResizingId(id);
    bringToFront(id);
    const boardRect = board.getBoundingClientRect();
    const wrapRect = wrap.getBoundingClientRect();
    const startX = e.clientX;
    const startY = e.clientY;
    const startW = wrapRect.width;
    const startH = wrapRect.height;
    const startLeft = wrapRect.left - boardRect.left + board.scrollLeft;
    const startTop = wrapRect.top - boardRect.top + board.scrollTop;
    const target = e.currentTarget;
    document.body.style.userSelect = 'none';
    function onMove(mv) {
      mv.preventDefault();
      let dx = mv.clientX - startX;
      let dy = mv.clientY - startY;
      let nx = startLeft;
      let ny = startTop;
      let nw = startW;
      let nh = startH;
      if (dir.includes('w')) { dx = Math.min(dx, startW - MIN_W); nx = Math.max(PAD, startLeft + dx); nw = startW - (nx - startLeft); }
      if (dir.includes('e')) { nw = Math.max(MIN_W, startW + dx); }
      if (dir.includes('n')) { dy = Math.min(dy, startH - MIN_H); ny = Math.max(PAD, startTop + dy); nh = startH - (ny - startTop); }
      if (dir.includes('s')) { nh = Math.max(MIN_H, startH + dy); }
      setSizes((prev) => ({ ...prev, [id]: { width: nw, height: nh } }));
      if (dir.includes('w') || dir.includes('n')) setPositions((prev) => ({ ...prev, [id]: { x: nx, y: ny } }));
    }
    function onUp(up) {
      target.removeEventListener('pointermove', onMove);
      target.removeEventListener('pointerup', onUp);
      target.removeEventListener('pointercancel', onUp);
      target.releasePointerCapture?.(up.pointerId);
      document.body.style.userSelect = '';
      setResizingId(null);
    }
    target.addEventListener('pointermove', onMove);
    target.addEventListener('pointerup', onUp);
    target.addEventListener('pointercancel', onUp);
  }

  useEffect(() => {
    const board = boardRef.current;
    if (!board) return;
    const update = () => setBoardSize({ width: board.clientWidth, height: board.clientHeight });
    update();
    const ro = new ResizeObserver(update);
    ro.observe(board);
    return () => ro.disconnect();
  }, []);

  useEffect(() => {
    try {
      const raw = localStorage.getItem(localStorageKey);
      if (raw) {
        const data = JSON.parse(raw);
        if (data.positions) setPositions(data.positions);
        if (data.sizes) setSizes(data.sizes);
        if (data.z) setZMap(data.z);
        if (data.layoutMode === 'manual') setLayoutMode('manual');
        if (typeof data.nextZ === 'number') nextZRef.current = data.nextZ;
        setHydrated(true);
        return;
      }
    } catch {}
    applyOwnerLayout();
    setHydrated(true);
  }, [applyOwnerLayout, localStorageKey]);

  useEffect(() => {
    if (!hydrated) return;
    const t = setTimeout(() => {
      try {
        localStorage.setItem(localStorageKey, JSON.stringify({ positions, sizes, z: zMap, layoutMode, nextZ: nextZRef.current }));
      } catch {}
    }, 200);
    return () => clearTimeout(t);
  }, [hydrated, localStorageKey, positions, sizes, zMap, layoutMode]);

  useEffect(() => {
    document.body.classList.toggle('public-space-dragging', Boolean(draggingId));
    document.body.classList.toggle('public-space-resizing', Boolean(resizingId));
    return () => {
      document.body.classList.remove('public-space-dragging');
      document.body.classList.remove('public-space-resizing');
    };
  }, [draggingId, resizingId]);

  const expires = expiryText(link);
  const boardHeight = Math.max(520, Math.min(980, 360 + safeArtifacts.length * 130));

  return (
    <main className="public-space-shell" data-public-space-canvas="true">
      <header className="public-space-topbar">
        <div>
          <div className="public-eyebrow">Shared space · share.madarX.io ready</div>
          <h1>{space?.name || 'Shared space'}</h1>
          <p>{safeArtifacts.length} artifact{safeArtifacts.length === 1 ? '' : 's'} · viewer layout is local to this browser</p>
        </div>
        <div className="public-space-actions">
          {expires && <span className="public-expiry">{expires}</span>}
          <button type="button" onClick={resetPublicLayout}>Reset layout</button>
        </div>
      </header>

      {safeArtifacts.length === 0 ? (
        <section className="public-empty">This space has no artifacts yet. New artifacts will appear here automatically.</section>
      ) : (
        <section ref={boardRef} className="public-canvas-board" style={{ minHeight: boardHeight }} aria-label="Shared artifact canvas">
          {safeArtifacts.map((a, idx) => {
            const L = getLayout(a, idx);
            const z = zMap[a.id] ?? (10 + idx);
            return (
              <article
                key={a.id}
                className={'public-artifact-window-wrap' + (draggingId === a.id ? ' is-dragging' : '')}
                data-dragging={draggingId === a.id ? 'true' : 'false'}
                data-resizing={resizingId === a.id ? 'true' : 'false'}
                style={{ transform: `translate3d(${L.x}px, ${L.y}px, 0)`, width: L.width, height: L.height, zIndex: z }}
                onPointerDown={() => bringToFront(a.id)}
              >
                <div className={'public-window' + (frontId === a.id ? ' is-front' : '')}>
                  <div className="public-winbar" onPointerDown={(e) => startDrag(e, a.id)} title="Drag to rearrange this shared view">
                    <i className="dot-close" aria-hidden="true" />
                    <i className="dot-minimize" aria-hidden="true" />
                    <i className="dot-zoom" aria-hidden="true" />
                    <b>{a.title || 'Artifact'}</b>
                    <span className="public-kind-badge">{a.kind || 'text'}</span>
                  </div>
                  <div className="public-win-content">
                    <PublicArtifactBody artifact={a} dragging={draggingId === a.id} resizing={resizingId === a.id} />
                  </div>
                </div>
                {['nw','n','ne','e','se','s','sw','w'].map((d) => (
                  <div key={d} className={'public-resize-edge public-resize-' + d} onPointerDown={(e) => startResize(e, a.id, d)} />
                ))}
              </article>
            );
          })}
        </section>
      )}

      <footer className="public-space-footer">Public read-only link · anonymous changes never write back to the owner workspace</footer>

      <style jsx global>{`
        *, *::before, *::after { box-sizing: border-box; }
        html, body { margin: 0; min-height: 100%; background: #0f1013; color: #f6f3ee; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
        body.public-space-dragging, body.public-space-dragging * { cursor: grabbing !important; user-select: none; }
        body.public-space-resizing, body.public-space-resizing * { user-select: none; }
      `}</style>
      <style jsx>{`
        .public-space-shell { min-height: 100vh; padding: 16px; background: radial-gradient(circle at top left, rgba(194,69,42,.22), transparent 36%), linear-gradient(135deg, #111318 0%, #191b21 42%, #0c0d10 100%); }
        .public-space-topbar { min-height: 92px; display: flex; align-items: center; justify-content: space-between; gap: 18px; padding: 18px 20px; border: 1px solid rgba(255,255,255,.10); border-radius: 22px; background: rgba(246,243,238,.08); box-shadow: 0 22px 60px rgba(0,0,0,.28), inset 0 1px 0 rgba(255,255,255,.08); backdrop-filter: blur(20px); }
        .public-eyebrow { font-size: 11px; font-weight: 800; letter-spacing: .13em; text-transform: uppercase; color: #d86d54; }
        .public-space-topbar h1 { margin: 5px 0 4px; font-size: clamp(26px, 3.2vw, 44px); line-height: 1; letter-spacing: -.05em; font-weight: 760; }
        .public-space-topbar p { margin: 0; color: rgba(246,243,238,.68); font-size: 13px; }
        .public-space-actions { display: flex; gap: 9px; align-items: center; flex-wrap: wrap; justify-content: flex-end; }
        .public-expiry { border-radius: 999px; border: 1px solid rgba(216,109,84,.36); background: rgba(194,69,42,.16); color: #ffd1c6; padding: 8px 12px; font-size: 12px; font-weight: 720; }
        .public-space-actions button { border: 0; border-radius: 999px; background: #f6f3ee; color: #111318; padding: 9px 13px; font-size: 12px; font-weight: 780; cursor: pointer; }
        .public-canvas-board { position: relative; margin-top: 14px; border: 1px solid rgba(255,255,255,.10); border-radius: 26px; overflow: auto; background: linear-gradient(180deg, rgba(246,243,238,.90), rgba(224,224,219,.88)); box-shadow: inset 0 1px 0 rgba(255,255,255,.92), 0 28px 80px rgba(0,0,0,.32); }
        .public-empty { margin-top: 14px; border: 1px solid rgba(255,255,255,.10); border-radius: 22px; padding: 34px; color: rgba(246,243,238,.72); background: rgba(246,243,238,.08); }
        .public-artifact-window-wrap { position: absolute; top: 0; left: 0; min-width: 280px; min-height: 190px; transition: transform .28s cubic-bezier(.32,.72,0,1), width .28s cubic-bezier(.32,.72,0,1), height .28s cubic-bezier(.32,.72,0,1); animation: public-window-in .28s cubic-bezier(.32,.72,0,1) both; }
        .public-artifact-window-wrap[data-dragging='true'], .public-artifact-window-wrap[data-resizing='true'] { transition: none; }
        @keyframes public-window-in { from { opacity: 0; transform: translate3d(0,12px,0) scale(.98); } to { opacity: 1; } }
        .public-window { width: 100%; height: 100%; display: flex; flex-direction: column; overflow: hidden; border-radius: 17px; background: rgba(255,255,255,.95); border: 1px solid rgba(20,22,26,.10); box-shadow: 0 18px 44px rgba(17,19,24,.18), inset 0 1px 0 rgba(255,255,255,.88); }
        .public-artifact-window-wrap.is-dragging .public-window, .public-window.is-front { box-shadow: 0 28px 72px rgba(17,19,24,.28), inset 0 1px 0 rgba(255,255,255,.9); }
        .public-winbar { height: 36px; flex: 0 0 36px; display: flex; align-items: center; gap: 8px; padding: 0 12px; cursor: grab; user-select: none; color: #111318; background: rgba(246,247,248,.94); border-bottom: 1px solid rgba(17,19,24,.08); }
        .public-winbar:active { cursor: grabbing; }
        .public-winbar i { width: 10px; height: 10px; border-radius: 50%; flex: 0 0 10px; }
        .dot-close { background: #ff5f57; }
        .dot-minimize { background: #ffbd2e; }
        .dot-zoom { background: #28c840; }
        .public-winbar b { min-width: 0; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; font-weight: 720; letter-spacing: -.01em; }
        .public-kind-badge { flex: 0 0 auto; border-radius: 7px; padding: 2px 7px; font-size: 10px; font-weight: 850; letter-spacing: .11em; text-transform: uppercase; color: #69717d; background: rgba(17,19,24,.07); }
        .public-win-content { flex: 1; min-height: 0; position: relative; overflow: hidden; color: #242933; }
        .public-win-content iframe { width: 100%; height: 100%; border: 0; display: block; background: #fff; }
        .public-win-md { height: 100%; overflow: auto; padding: 16px 20px; font-size: 13px; line-height: 1.62; color: #2c3038; }
        .public-win-md p { margin: .35em 0; }
        .public-win-md ul, .public-win-md ol { padding-left: 1.35em; }
        .public-win-md h1 { font-size: 1.55em; margin: .6em 0 .3em; }
        .public-win-md h2 { font-size: 1.25em; margin: .7em 0 .3em; }
        .public-win-md h3 { font-size: 1.08em; margin: .6em 0 .25em; }
        .public-win-code { height: 100%; overflow: auto; margin: 0; padding: 16px; background: #f6f8fa; color: #1f2328; font-size: 12px; line-height: 1.55; }
        .public-drag-blocker, .public-resize-blocker { position: absolute; inset: 0; z-index: 3; background: transparent; }
        .public-resize-edge { position: absolute; z-index: 4; }
        .public-resize-n { top: -3px; left: 14px; right: 14px; height: 7px; cursor: ns-resize; }
        .public-resize-s { bottom: -3px; left: 14px; right: 14px; height: 7px; cursor: ns-resize; }
        .public-resize-w { left: -3px; top: 14px; bottom: 14px; width: 7px; cursor: ew-resize; }
        .public-resize-e { right: -3px; top: 14px; bottom: 14px; width: 7px; cursor: ew-resize; }
        .public-resize-nw, .public-resize-ne, .public-resize-sw, .public-resize-se { width: 16px; height: 16px; }
        .public-resize-nw { top: -3px; left: -3px; cursor: nwse-resize; }
        .public-resize-ne { top: -3px; right: -3px; cursor: nesw-resize; }
        .public-resize-sw { bottom: -3px; left: -3px; cursor: nesw-resize; }
        .public-resize-se { bottom: -3px; right: -3px; cursor: nwse-resize; }
        .public-space-footer { padding: 14px 4px 2px; text-align: center; color: rgba(246,243,238,.46); font-size: 12px; }
        @media (max-width: 720px) {
          .public-space-shell { padding: 10px; }
          .public-space-topbar { align-items: flex-start; flex-direction: column; border-radius: 18px; }
          .public-space-actions { justify-content: flex-start; }
          .public-canvas-board { border-radius: 18px; }
        }
      `}</style>
    </main>
  );
}
