'use client';

/**
 * space-share-modal.jsx — Share a dashboard space.
 *
 * Two ways to share (the user picked "Both"):
 *   1. Public link  — /share/space/<token>, no login. Live: artifacts created in
 *      or moved into the space later are included automatically. Per-share expiry,
 *      view cap, optional email-OTP. Backed by /api/dashboard/spaces/[id]/share-link.
 *   2. Org workspace — publish to the Supabase org (teammates only). Shown only
 *      when shared cloud is configured. Backed by /api/shared/spaces/*.
 */

import { useCallback, useEffect, useState } from 'react';
import { createPortal } from 'react-dom';

function IconClose() {
  return (
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" aria-hidden="true">
      <line x1="6" y1="6" x2="18" y2="18" /><line x1="18" y1="6" x2="6" y2="18" />
    </svg>
  );
}

function fmtDate(iso) {
  if (!iso) return 'never';
  try { return new Date(iso).toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' }); }
  catch { return iso; }
}

export default function SpaceShareModal({ spaceId, spaceName, onClose }) {
  const [links, setLinks] = useState([]);
  const [loading, setLoading] = useState(true);
  const [creating, setCreating] = useState(false);
  const [error, setError] = useState('');
  const [copiedId, setCopiedId] = useState(null);

  const [expiresInDays, setExpiresInDays] = useState(7);
  const [maxViews, setMaxViews] = useState(50);
  const [requireOtp, setRequireOtp] = useState(false);

  const [cloudReady, setCloudReady] = useState(false);
  const [cloudStatus, setCloudStatus] = useState(null);
  const [cloudVisibility, setCloudVisibility] = useState('org');
  const [cloudBusy, setCloudBusy] = useState(false);

  // Portal target — guard against SSR (document is undefined on the server).
  const [mounted, setMounted] = useState(false);
  useEffect(() => { setMounted(true); }, []);
  // Lock body scroll while open.
  useEffect(() => {
    const prev = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => { document.body.style.overflow = prev; };
  }, []);

  const origin = typeof window !== 'undefined' ? window.location.origin : '';
  const linkUrl = useCallback((token) => `${origin}/share/space/${token}`, [origin]);

  const refresh = useCallback(async () => {
    setLoading(true);
    try {
      const [lr, sr] = await Promise.all([
        fetch(`/api/dashboard/spaces/${spaceId}/share-link`, { cache: 'no-store' }),
        fetch(`/api/shared/spaces/status?local_space_id=${encodeURIComponent(spaceId)}&space_type=dashboard_space`, { cache: 'no-store' }),
      ]);
      const ld = await lr.json().catch(() => ({}));
      if (lr.ok) setLinks(ld.data || []);
      const sd = await sr.json().catch(() => ({}));
      if (sr.ok) { setCloudReady(Boolean(sd.cloud_ready)); setCloudStatus(sd.status || null); }
    } catch { setError('Failed to load share state.'); }
    finally { setLoading(false); }
  }, [spaceId]);

  useEffect(() => { if (spaceId) refresh(); }, [spaceId, refresh]);

  async function createLink(e) {
    e.preventDefault();
    setCreating(true); setError('');
    try {
      const res = await fetch(`/api/dashboard/spaces/${spaceId}/share-link`, {
        method: 'POST', headers: { 'content-type': 'application/json' },
        body: JSON.stringify({
          expires_in_days: Number(expiresInDays) || null,
          max_views: Number(maxViews) || null,
          require_email_otp: requireOtp,
        }),
      });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) { setError(data.error || 'Failed to create link.'); return; }
      await refresh();
    } catch { setError('Failed to create link.'); }
    finally { setCreating(false); }
  }

  async function revokeLink(linkId) {
    try {
      const res = await fetch(`/api/dashboard/spaces/${spaceId}/share-link/${linkId}`, { method: 'DELETE' });
      if (res.ok) setLinks((prev) => prev.filter((l) => l.id !== linkId));
    } catch { /* ignore */ }
  }

  async function copyLink(token, id) {
    try { await navigator.clipboard.writeText(linkUrl(token)); setCopiedId(id); setTimeout(() => setCopiedId(null), 1500); }
    catch { /* ignore */ }
  }

  async function publishCloud() {
    setCloudBusy(true); setError('');
    try {
      const res = await fetch('/api/shared/spaces/publish', {
        method: 'POST', headers: { 'content-type': 'application/json' },
        body: JSON.stringify({ space_type: 'dashboard_space', space_id: spaceId, visibility: cloudVisibility }),
      });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) { setError(data.error === 'shared_cloud_not_configured' ? 'Supabase cloud is not configured.' : (data.error || 'Publish failed.')); return; }
      setCloudStatus(data.status || null);
    } catch { setError('Publish failed.'); }
    finally { setCloudBusy(false); }
  }

  async function unpublishCloud() {
    setCloudBusy(true); setError('');
    try {
      const res = await fetch('/api/shared/spaces/unpublish', {
        method: 'POST', headers: { 'content-type': 'application/json' },
        body: JSON.stringify({ local_space_id: spaceId, space_type: 'dashboard_space' }),
      });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) { setError(data.error || 'Unpublish failed.'); return; }
      setCloudStatus(data.status || null);
    } catch { setError('Unpublish failed.'); }
    finally { setCloudBusy(false); }
  }

  const isPublished = cloudStatus?.shared || cloudStatus?.status === 'published';

  if (!mounted) return null;

  return createPortal(
    <div className="space-share-overlay" onClick={onClose}>
      <div className="space-share-modal" onClick={(e) => e.stopPropagation()} role="dialog" aria-modal="true" aria-label={`Share ${spaceName}`}>
        <div className="ssm-head">
          <div>
            <div className="ssm-eyebrow">Share space</div>
            <h2 className="ssm-title">{spaceName}</h2>
          </div>
          <button type="button" className="ssm-close" onClick={onClose} aria-label="Close"><IconClose /></button>
        </div>

        {error ? <div className="ssm-error">{error}</div> : null}

        {/* Public link */}
        <section className="ssm-section">
          <h3 className="ssm-section-title">Public link</h3>
          <p className="ssm-note">Anyone with the link can view every artifact in this space. New and moved-in artifacts are included automatically.</p>

          <form className="ssm-form" onSubmit={createLink}>
            <label className="ssm-field">
              <span>Expires in (days)</span>
              <input type="number" min="0" max="90" value={expiresInDays} onChange={(e) => setExpiresInDays(e.target.value)} />
            </label>
            <label className="ssm-field">
              <span>Max views</span>
              <input type="number" min="0" value={maxViews} onChange={(e) => setMaxViews(e.target.value)} />
            </label>
            <label className="ssm-check">
              <input type="checkbox" checked={requireOtp} onChange={(e) => setRequireOtp(e.target.checked)} />
              <span>Require email verification</span>
            </label>
            <button type="submit" className="ssm-btn ssm-btn-primary" disabled={creating}>{creating ? 'Creating…' : 'Create link'}</button>
          </form>

          <div className="ssm-links">
            {loading ? <div className="ssm-muted">Loading…</div> : null}
            {!loading && links.length === 0 ? <div className="ssm-muted">No active links.</div> : null}
            {links.map((l) => (
              <div className="ssm-link" key={l.id}>
                <div className="ssm-link-main">
                  <input className="ssm-link-url" readOnly value={linkUrl(l.token)} onFocus={(e) => e.target.select()} />
                  <button type="button" className="ssm-btn ssm-btn-sm" onClick={() => copyLink(l.token, l.id)}>{copiedId === l.id ? 'Copied' : 'Copy'}</button>
                  <button type="button" className="ssm-btn ssm-btn-sm ssm-btn-danger" onClick={() => revokeLink(l.id)}>Revoke</button>
                </div>
                <div className="ssm-link-meta">
                  Expires {fmtDate(l.expires_at)} · {l.access_count}{l.max_views != null ? `/${l.max_views}` : ''} views{l.require_email_otp ? ' · email-gated' : ''}
                </div>
              </div>
            ))}
          </div>
        </section>

        {/* Org workspace */}
        {cloudReady ? (
          <section className="ssm-section">
            <h3 className="ssm-section-title">Org workspace</h3>
            <p className="ssm-note">Publish this space to your organization. Only signed-in teammates can see it.</p>
            {isPublished ? (
              <div className="ssm-cloud-status">
                <span className="ssm-badge ssm-badge-on">Published</span>
                <span className="ssm-muted">{cloudStatus?.visibility || 'org'} · {cloudStatus?.resource_count ?? 0} artifacts indexed</span>
                <button type="button" className="ssm-btn ssm-btn-sm ssm-btn-danger" onClick={unpublishCloud} disabled={cloudBusy}>{cloudBusy ? '…' : 'Unpublish'}</button>
              </div>
            ) : (
              <div className="ssm-form">
                <label className="ssm-field">
                  <span>Visibility</span>
                  <select value={cloudVisibility} onChange={(e) => setCloudVisibility(e.target.value)}>
                    <option value="org">Whole organization</option>
                    <option value="team">Team</option>
                    <option value="private">Private</option>
                  </select>
                </label>
                <button type="button" className="ssm-btn ssm-btn-primary" onClick={publishCloud} disabled={cloudBusy}>{cloudBusy ? 'Publishing…' : 'Publish to org'}</button>
              </div>
            )}
          </section>
        ) : null}
      </div>
    </div>,
    document.body
  );
}
