/**
 * app/share/[token]/page.js — Public read-only artifact viewer.
 *
 * No session required. Verifies the share token server-side,
 * handles the OTP gate if required, and renders the artifact content
 * in a minimal layout with no madarX navigation chrome.
 *
 * Content rendering:
 *   - HTML / UI artifacts: sandboxed iframe (raw content isolated from parent)
 *   - Markdown: server-rendered via simpleMarkdownToHtml (escapes all user input first)
 *   - JSON: syntax-highlighted pre block
 *   - Plain text: pre block
 *
 * XSS safety: simpleMarkdownToHtml() calls escapeHtml() on ALL input before
 * any transformation. No raw user content is ever injected into dangerouslySetInnerHTML.
 * HTML artifacts are served inside a sandboxed iframe, isolated from the parent document.
 *
 * "Sign in to madarX" link is rendered only when MADARX_AUTH_MODE === 'supabase'.
 */

import { verifyShareLink } from '@/lib/artifact-acl.js';
import { getAuthMode } from '@/lib/auth.js';
import ShareOtpGate from './otp-gate.jsx';

export const dynamic = 'force-dynamic';

// This route renders under the app root layout, which already provides
// <html>/<body>. AppChrome only strips the sidebar for /share/* — it does not
// hand us a new document root. Rendering our own <html> nests <html> inside a
// <div> and breaks hydration, so the layout below is a plain in-page wrapper
// and the document title comes from generateMetadata.

export async function generateMetadata({ params }) {
  const { token } = await params;
  const result = await verifyShareLink(token, null).catch(() => null);
  const title = result?.ok ? result.artifact?.title : null;
  return {
    title: title ? `${title} — madarX` : 'Shared artifact — madarX',
    robots: { index: false, follow: false },
  };
}

const SHARE_STYLES = `
  .share-wrap { max-width: 800px; margin: 0 auto; padding: 2.5rem 1.5rem; min-height: 100vh; background: #fafafa; color: #1a1a1a; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
  .share-header { margin-bottom: 2rem; padding-bottom: 1.25rem; border-bottom: 1px solid #e5e7eb; }
  .share-title { font-size: 1.5rem; font-weight: 600; line-height: 1.3; }
  .share-meta { margin-top: 0.5rem; font-size: 0.8125rem; color: #666; }
  .share-markdown h1, .share-markdown h2, .share-markdown h3 { margin: 1.5rem 0 0.75rem; font-weight: 600; }
  .share-markdown p { margin-bottom: 1rem; }
  .share-markdown li { margin-left: 1.5rem; margin-bottom: 0.25rem; }
  .share-markdown code { background: #f0f0f0; padding: 0.1em 0.3em; border-radius: 3px; font-size: 0.875em; }
  .share-markdown strong { font-weight: 600; }
`;

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

function daysUntil(iso) {
  if (!iso) return null;
  const diff = new Date(iso).getTime() - Date.now();
  if (diff <= 0) return 0;
  return Math.ceil(diff / (1000 * 60 * 60 * 24));
}

/**
 * Escape HTML entities. Applied FIRST in simpleMarkdownToHtml so no user
 * content reaches dangerouslySetInnerHTML unescaped.
 */
function escapeHtml(str) {
  return String(str)
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;');
}

/**
 * Minimal markdown-to-HTML converter.
 * SECURITY: escapeHtml() is called on the entire input first, so all angle
 * brackets and ampersands from user content are neutralised before any regex
 * replacement runs. The replacements only introduce a fixed set of safe HTML
 * tags (h1-h3, strong, em, code, li, p) — never script, style, or event attrs.
 */
function simpleMarkdownToHtml(md) {
  if (!md) return '';
  // Step 1: escape ALL user content. No raw user strings reach the DOM.
  let html = escapeHtml(md);
  // Step 2: apply structural transformations on the now-safe escaped string.
  html = html.replace(/^### (.+)$/gm, '<h3>$1</h3>');
  html = html.replace(/^## (.+)$/gm, '<h2>$1</h2>');
  html = html.replace(/^# (.+)$/gm, '<h1>$1</h1>');
  html = html.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>');
  html = html.replace(/\*(.+?)\*/g, '<em>$1</em>');
  html = html.replace(/`([^`]+)`/g, '<code>$1</code>');
  html = html.replace(/^\- (.+)$/gm, '<li>$1</li>');
  html = html.replace(/\n{2,}/g, '</p><p>');
  return '<p>' + html + '</p>';
}

export default async function SharePage({ params }) {
  const { token } = await params;
  const authMode = getAuthMode();

  // Verify the link (without recording access — the API route does that).
  const result = await verifyShareLink(token, null);

  // Error states.
  if (!result.ok) {
    const messages = {
      expired:         { title: 'Link Expired',           body: 'This share link has expired and is no longer accessible.' },
      revoked:         { title: 'Link Revoked',           body: 'This share link has been revoked by its owner.' },
      view_cap_reached:{ title: 'View Limit Reached',     body: 'This share link has reached its maximum number of views.' },
      not_found:       { title: 'Not Found',              body: 'This share link does not exist or has been removed.' },
    };
    const msg = messages[result.reason] || messages.not_found;

    return (
      <ShareLayout>
        <div style={{ textAlign: 'center', padding: '4rem 2rem' }}>
          <h1 style={{ fontSize: '1.5rem', fontWeight: 600, marginBottom: '0.75rem' }}>{msg.title}</h1>
          <p style={{ color: '#666', maxWidth: '36ch', margin: '0 auto' }}>{msg.body}</p>
          {authMode === 'supabase' && (
            <a href="/" style={{ display: 'inline-block', marginTop: '2rem', color: '#1a1a1a', textDecoration: 'underline', fontSize: '0.875rem' }}>
              Sign in to madarX
            </a>
          )}
        </div>
      </ShareLayout>
    );
  }

  const { link, artifact } = result;

  // OTP gate: if required, render the client-side OTP form.
  // node:sqlite rows have a null prototype and cannot cross the Server→Client
  // boundary; hand the gate a plain object with only the fields it reads.
  if (link.require_email_otp === 1) {
    const otpArtifact = { title: artifact.title ?? null, kind: artifact.kind ?? null };
    return (
      <ShareLayout artifact={artifact} link={link}>
        <ShareOtpGate token={token} artifact={otpArtifact} />
      </ShareLayout>
    );
  }

  const kind = (artifact.kind || '').toLowerCase();
  const content = artifact.content || artifact.source_md || '';
  const expiryDays = daysUntil(link.expires_at);

  return (
    <ShareLayout artifact={artifact} link={link}>
      {link.expires_at && (
        <div style={{
          padding: '0.5rem 1rem',
          background: expiryDays <= 1 ? '#fff3cd' : '#f0f4f8',
          borderRadius: '6px',
          marginBottom: '1.5rem',
          fontSize: '0.8125rem',
          color: expiryDays <= 1 ? '#856404' : '#555',
        }}>
          {expiryDays === 0
            ? 'This link expires today.'
            : expiryDays === 1
            ? 'This link expires tomorrow.'
            : `This link expires in ${expiryDays} days.`}
          {' '}Expires {formatDate(link.expires_at)}.
        </div>
      )}
      <ArtifactContent kind={kind} content={content} title={artifact.title} />
      {authMode === 'supabase' && (
        <div style={{ marginTop: '3rem', paddingTop: '1.5rem', borderTop: '1px solid #eee', textAlign: 'center' }}>
          <a href="/" style={{ color: '#555', textDecoration: 'underline', fontSize: '0.8125rem' }}>
            Sign in to madarX
          </a>
        </div>
      )}
    </ShareLayout>
  );
}

function ArtifactContent({ kind, content, title }) {
  if (kind === 'html' || kind === 'ui' || kind === 'mines_investor_presentation' || kind === 'mines_project_package') {
    // HTML artifacts are isolated in a sandboxed iframe — the raw HTML never
    // reaches the parent document DOM.
    return (
      <iframe
        title={title || 'Artifact'}
        srcDoc={content}
        sandbox="allow-scripts allow-same-origin"
        style={{
          width: '100%',
          minHeight: '60vh',
          border: '1px solid #e5e7eb',
          borderRadius: '8px',
          background: '#fff',
        }}
      />
    );
  }

  if (kind === 'md' || kind === 'markdown') {
    // simpleMarkdownToHtml escapes all input before transformation — safe.
    const safeHtml = simpleMarkdownToHtml(content);
    return (
      <div
        className="share-markdown"
        style={{ lineHeight: 1.7, color: '#1a1a1a' }}
        // eslint-disable-next-line react/no-danger
        dangerouslySetInnerHTML={{ __html: safeHtml }}
      />
    );
  }

  if (kind === 'json') {
    let formatted = content;
    try { formatted = JSON.stringify(JSON.parse(content), null, 2); } catch {}
    return (
      <pre style={{
        background: '#f6f8fa', padding: '1.25rem', borderRadius: '8px',
        overflow: 'auto', fontSize: '0.8125rem', lineHeight: 1.6,
        border: '1px solid #e5e7eb',
      }}>
        <code>{formatted}</code>
      </pre>
    );
  }

  return (
    <pre style={{
      background: '#f6f8fa', padding: '1.25rem', borderRadius: '8px',
      overflow: 'auto', fontSize: '0.875rem', lineHeight: 1.6,
      whiteSpace: 'pre-wrap', wordBreak: 'break-word',
      border: '1px solid #e5e7eb',
    }}>
      {content}
    </pre>
  );
}

function ShareLayout({ artifact, link, children }) {
  const title = artifact?.title || 'Shared artifact';
  const createdAt = artifact?.created_at;

  return (
    <div className="share-wrap">
      <style>{SHARE_STYLES}</style>
      {artifact && (
        <div className="share-header">
          <h1 className="share-title">{title}</h1>
          {createdAt && (
            <p className="share-meta">Created {formatDate(createdAt)}</p>
          )}
        </div>
      )}
      {children}
    </div>
  );
}
