// ── Render (managed Node/Bun apps) dashboard ────────────────────────────

function RenderPage({ user }) {
  const [projects, setProjects] = useState([]);
  const [loading, setLoading] = useState(true);
  const [selected, setSelected] = useState(null);

  const loadProjects = useCallback(async () => {
    setLoading(true);
    try {
      const list = await api('/api/render/projects');
      setProjects(Array.isArray(list) ? list : []);
    } catch { setProjects([]); }
    finally { setLoading(false); }
  }, []);

  useEffect(() => { loadProjects(); }, [loadProjects]);

  if (selected) {
    return <RenderProjectDetail
      projectId={selected}
      onBack={() => { setSelected(null); loadProjects(); }}
      user={user}
    />;
  }

  return (
    <>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}>
        <h2 style={{ margin: 0 }}>Render</h2>
        <button type="button" className="btn-sm btn-ghost" onClick={loadProjects} disabled={loading}>
          {loading ? 'Loading…' : '↻ Refresh'}
        </button>
      </div>
      <div className="page-sub" style={{ marginBottom: 24 }}>
        Managed Node/Bun apps — init from the CLI, then build, configure, and deploy here.
      </div>

      {!loading && projects.length === 0 && (
        <div className="profile-card" style={{ maxWidth: 640, textAlign: 'center', padding: 40 }}>
          <div style={{ fontSize: 40, marginBottom: 12 }}>📦</div>
          <h3>No projects yet</h3>
          <p style={{ color: 'var(--text-dim)', marginTop: 8 }}>
            Upload your first project from the CLI:
          </p>
          <pre style={{
            background: 'var(--bg)', border: '1px solid var(--border)', borderRadius: 8,
            padding: 16, fontSize: 13, fontFamily: 'SF Mono,Menlo,Consolas,monospace',
            color: 'var(--accent)', margin: '16px auto 0', maxWidth: 400, textAlign: 'left',
          }}>$ vibey render-init ./my-app</pre>
        </div>
      )}

      {projects.length > 0 && (
        <div style={{ display: 'grid', gap: 12 }}>
          {projects.map(p => (
            <div key={p.id} className="profile-card" style={{
              cursor: 'pointer', maxWidth: 'none', padding: '16px 20px',
              display: 'flex', alignItems: 'center', justifyContent: 'space-between',
              transition: 'border-color 0.2s',
            }}
              onClick={() => setSelected(p.id)}
              onMouseEnter={e => e.currentTarget.style.borderColor = 'var(--accent)'}
              onMouseLeave={e => e.currentTarget.style.borderColor = 'var(--border)'}
            >
              <div style={{ display: 'flex', alignItems: 'center', gap: 14, minWidth: 0 }}>
                <RenderStatusDot status={p.status} live={p.live} />
                <div style={{ minWidth: 0 }}>
                  <div style={{ fontWeight: 600, fontSize: 15 }}>{p.name}</div>
                  <div style={{ fontSize: 12, color: 'var(--text-dim)', marginTop: 2 }}>
                    {p.id} · {p.runtime}
                  </div>
                </div>
              </div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 16, flexShrink: 0 }}>
                <span style={{ fontSize: 12, color: 'var(--text-dim)' }}>
                  {new Date(p.created_at).toLocaleDateString()}
                </span>
                <span style={{ fontSize: 11, fontWeight: 600, textTransform: 'uppercase', color: renderStatusColor(p.status, p.live) }}>
                  {p.live ? 'live' : p.status}
                </span>
                <span style={{ color: 'var(--text-dim)' }}>›</span>
              </div>
            </div>
          ))}
        </div>
      )}

      <BlueprintConfigurator />
    </>
  );
}

// ── Blueprint Configurator ──────────────────────────────────────────────

const BLUEPRINT_PRESETS = [
  { id: 'express',  label: 'Express',  runtime: 'node', build: 'npm install',                     start: 'node server.js',    envHint: 'PORT is set automatically' },
  { id: 'nextjs',   label: 'Next.js',  runtime: 'node', build: 'npm install && npm run build',    start: 'npm start',         envHint: 'Next.js reads PORT by default' },
  { id: 'nestjs',   label: 'NestJS',   runtime: 'node', build: 'npm install && npm run build',    start: 'node dist/main',    envHint: '' },
  { id: 'remix',    label: 'Remix',    runtime: 'node', build: 'npm install && npm run build',    start: 'npm start',         envHint: '' },
  { id: 'fastify',  label: 'Fastify',  runtime: 'node', build: 'npm install',                     start: 'node server.js',    envHint: 'Bind to 0.0.0.0, not localhost' },
  { id: 'hono',     label: 'Hono',     runtime: 'node', build: 'npm install',                     start: 'node index.js',     envHint: '' },
  { id: 'vite-ssr', label: 'Vite SSR', runtime: 'node', build: 'npm install && npm run build',    start: 'node server.js',    envHint: '' },
  { id: 'bun',      label: 'Bun',      runtime: 'bun',  build: 'bun install',                     start: 'bun run start',     envHint: 'Bun reads PORT from env' },
  { id: 'custom',   label: 'Custom',   runtime: 'node', build: '',                                start: '',                  envHint: '' },
];

function BlueprintConfigurator() {
  const [preset, setPreset] = useState(null);
  const [name, setName] = useState('my-app');
  const [runtime, setRuntime] = useState('node');
  const [buildCmd, setBuildCmd] = useState('npm install');
  const [startCmd, setStartCmd] = useState('npm start');
  const [envRows, setEnvRows] = useState([]);
  const [copied, setCopied] = useState(false);

  const selectPreset = (p) => {
    setPreset(p.id);
    setRuntime(p.runtime);
    setBuildCmd(p.build);
    setStartCmd(p.start);
  };

  const addEnvRow = () => setEnvRows([...envRows, { key: '', value: '', secret: false }]);
  const removeEnvRow = (i) => setEnvRows(envRows.filter((_, j) => j !== i));
  const updateEnvRow = (i, field, val) => {
    const next = [...envRows];
    next[i] = { ...next[i], [field]: val };
    setEnvRows(next);
  };

  const yaml = useMemo(() => {
    let out = `name: ${name}\nruntime: ${runtime}\nbuildCommand: ${buildCmd}\nstartCommand: ${startCmd}`;
    const validEnvs = envRows.filter(e => e.key.trim());
    if (validEnvs.length > 0) {
      out += '\nenvVars:';
      for (const e of validEnvs) {
        if (e.secret || !e.value.trim()) {
          out += `\n  - key: ${e.key.trim()}\n    sync: false`;
        } else {
          out += `\n  - key: ${e.key.trim()}\n    value: ${e.value}`;
        }
      }
    }
    return out;
  }, [name, runtime, buildCmd, startCmd, envRows]);

  const doCopy = async () => {
    try {
      await navigator.clipboard.writeText(yaml);
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    } catch {}
  };

  const bpInputStyle = {
    background: 'var(--bg)', border: '1px solid var(--border)', borderRadius: 6,
    padding: '8px 12px', fontSize: 13, color: 'var(--text)', width: '100%',
    fontFamily: 'inherit', outline: 'none',
  };

  return (
    <div style={{ marginTop: 24, display: 'grid', gap: 16 }}>
      <div className="profile-card" style={{ maxWidth: 'none' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <h3 style={{ margin: 0 }}>Blueprint configurator</h3>
          <span style={{ fontSize: 12, color: 'var(--text-dim)' }}>vibey-render.yaml</span>
        </div>
        <p style={{ fontSize: 12, color: 'var(--text-dim)', marginTop: 6, marginBottom: 16 }}>
          Pick a preset, customise, then copy the YAML into your project root as <code style={{ fontSize: 11 }}>vibey-render.yaml</code>.
          It auto-configures everything on <code style={{ fontSize: 11 }}>vibey render-init</code>.
        </p>

        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginBottom: 20 }}>
          {BLUEPRINT_PRESETS.map(p => (
            <button key={p.id} onClick={() => selectPreset(p)} style={{
              padding: '6px 14px', borderRadius: 6, fontSize: 12, fontWeight: 500,
              cursor: 'pointer', transition: 'all 0.15s',
              background: preset === p.id ? 'var(--accent)' : 'var(--surface)',
              color: preset === p.id ? '#fff' : 'var(--text)',
              border: preset === p.id ? '1px solid var(--accent)' : '1px solid var(--border)',
            }}>
              {p.label}
            </button>
          ))}
        </div>

        {preset && (() => {
          const p = BLUEPRINT_PRESETS.find(x => x.id === preset);
          return p && p.envHint ? (
            <div style={{
              background: 'var(--surface-hover)', border: '1px solid var(--border)', borderRadius: 6,
              padding: '8px 14px', fontSize: 12, color: 'var(--text-dim)', marginBottom: 16,
            }}>
              Tip: {p.envHint}
            </div>
          ) : null;
        })()}

        <div style={{ display: 'grid', gap: 12 }}>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
            <div>
              <label style={bpLabelStyle}>App name</label>
              <input style={bpInputStyle} value={name} onChange={e => setName(e.target.value)} placeholder="my-app" />
            </div>
            <div>
              <label style={bpLabelStyle}>Runtime</label>
              <select style={{ ...bpInputStyle, cursor: 'pointer' }} value={runtime} onChange={e => setRuntime(e.target.value)}>
                <option value="node">Node.js</option>
                <option value="bun">Bun</option>
              </select>
            </div>
          </div>
          <div>
            <label style={bpLabelStyle}>Build command</label>
            <input style={bpInputStyle} value={buildCmd} onChange={e => setBuildCmd(e.target.value)} placeholder="npm install" />
          </div>
          <div>
            <label style={bpLabelStyle}>Start command</label>
            <input style={bpInputStyle} value={startCmd} onChange={e => setStartCmd(e.target.value)} placeholder="npm start" />
          </div>
        </div>

        <div style={{ marginTop: 16 }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}>
            <label style={bpLabelStyle}>Environment variables</label>
            <button className="btn-sm btn-ghost" onClick={addEnvRow} style={{ fontSize: 11 }}>+ Add var</button>
          </div>
          {envRows.map((row, i) => (
            <div key={i} style={{ display: 'flex', gap: 8, marginBottom: 6, alignItems: 'center' }}>
              <input style={{ ...bpInputStyle, flex: 1 }} value={row.key} onChange={e => updateEnvRow(i, 'key', e.target.value)} placeholder="KEY" />
              <input style={{ ...bpInputStyle, flex: 2 }} value={row.value} onChange={e => updateEnvRow(i, 'value', e.target.value)}
                placeholder={row.secret ? '(set in dashboard)' : 'value'} disabled={row.secret} />
              <label style={{ fontSize: 11, color: 'var(--text-dim)', display: 'flex', alignItems: 'center', gap: 4, whiteSpace: 'nowrap', cursor: 'pointer' }}>
                <input type="checkbox" checked={row.secret} onChange={e => updateEnvRow(i, 'secret', e.target.checked)} />
                secret
              </label>
              <button className="btn-sm btn-ghost" onClick={() => removeEnvRow(i)} style={{ color: 'var(--red)', padding: '4px 6px', fontSize: 11 }}>✕</button>
            </div>
          ))}
        </div>
      </div>

      <div className="profile-card" style={{ maxWidth: 'none', position: 'relative' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}>
          <h3 style={{ margin: 0, fontSize: 14 }}>Generated vibey-render.yaml</h3>
          <button className="btn-primary" onClick={doCopy} style={{ fontSize: 12, padding: '6px 16px' }}>
            {copied ? '✓ Copied!' : 'Copy'}
          </button>
        </div>
        <pre style={{
          background: '#0d1117', border: '1px solid var(--border)', borderRadius: 8,
          padding: 16, fontFamily: 'SF Mono,Menlo,Consolas,monospace', fontSize: 12,
          color: '#c9d1d9', whiteSpace: 'pre-wrap', lineHeight: 1.7, margin: 0,
        }}>{yaml}</pre>
        <p style={{ fontSize: 11, color: 'var(--text-dim)', marginTop: 10, marginBottom: 0 }}>
          Save this as <code style={{ fontSize: 10 }}>vibey-render.yaml</code> in your project root, then run <code style={{ fontSize: 10 }}>vibey render-init .</code>
        </p>
      </div>

      <div className="profile-card" style={{ maxWidth: 'none' }}>
        <h3>Quick start</h3>
        <div style={{ fontSize: 13, color: 'var(--text-dim)', lineHeight: 1.8 }}>
          <pre style={{
            background: 'var(--bg)', border: '1px solid var(--border)', borderRadius: 8,
            padding: 16, fontSize: 12, fontFamily: 'SF Mono,Menlo,Consolas,monospace',
            color: 'var(--text)', whiteSpace: 'pre-wrap', margin: 0,
          }}>{`# 1. Save vibey-render.yaml in your project (use configurator above)
# 2. Upload from CLI:
$ vibey render-init ./my-app

# 3. Open this dashboard → configure any secret env vars → Deploy`}</pre>
        </div>
      </div>
    </div>
  );
}

const bpLabelStyle = { display: 'block', fontSize: 11, fontWeight: 600, color: 'var(--text-dim)', marginBottom: 4, textTransform: 'uppercase', letterSpacing: '0.5px' };

// ── Status helpers ──────────────────────────────────────────────────────

function renderStatusColor(status, live) {
  if (live) return 'var(--green)';
  switch (status) {
    case 'running': return 'var(--green)';
    case 'building': return 'var(--yellow)';
    case 'created': return 'var(--blue)';
    case 'stopped': return 'var(--text-dim)';
    case 'failed': return 'var(--red)';
    default: return 'var(--text-dim)';
  }
}

function RenderStatusDot({ status, live }) {
  const color = renderStatusColor(status, live);
  const pulse = live || status === 'building';
  return (
    <span style={{
      width: 10, height: 10, borderRadius: '50%', background: color, flexShrink: 0,
      boxShadow: pulse ? `0 0 6px ${color}` : 'none',
      animation: pulse ? 'renderPulse 2s ease-in-out infinite' : 'none',
    }} />
  );
}

// ── Project Detail ──────────────────────────────────────────────────────

function RenderProjectDetail({ projectId, onBack }) {
  const [project, setProject] = useState(null);
  const [tab, setTab] = useState('overview');
  const [loading, setLoading] = useState(true);
  const [deploying, setDeploying] = useState(false);
  const [buildLog, setBuildLog] = useState('');

  const loadProject = useCallback(async () => {
    setLoading(true);
    try {
      const p = await api(`/api/render/projects/${projectId}`);
      setProject(p);
    } catch {}
    finally { setLoading(false); }
  }, [projectId]);

  useEffect(() => { loadProject(); }, [loadProject]);

  const doDeploy = async () => {
    setDeploying(true);
    setBuildLog('');
    setTab('logs');
    try {
      const result = await api(`/api/render/projects/${projectId}/deploy`, { method: 'POST' });
      setBuildLog(result.build_log || '');
      await loadProject();
    } catch (e) { setBuildLog('Deploy failed: ' + e.message); }
    finally { setDeploying(false); }
  };

  const doStop = async () => {
    try {
      await api(`/api/render/projects/${projectId}/stop`, { method: 'POST' });
      await loadProject();
    } catch {}
  };

  const doDelete = async () => {
    if (!confirm('Delete this project? The running process will be stopped.')) return;
    try {
      await api(`/api/render/projects/${projectId}`, { method: 'DELETE' });
      onBack();
    } catch {}
  };

  if (loading && !project) {
    return <div style={{ padding: 40, textAlign: 'center', color: 'var(--text-dim)' }}>Loading…</div>;
  }

  if (!project) {
    return (
      <div style={{ padding: 40, textAlign: 'center' }}>
        <p>Project not found.</p>
        <button className="btn-sm btn-ghost" onClick={onBack} style={{ marginTop: 16 }}>← Back</button>
      </div>
    );
  }

  const tabs = ['overview', 'env', 'logs', 'deployments'];

  return (
    <>
      <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 4 }}>
        <button className="btn-sm btn-ghost" onClick={onBack}>←</button>
        <RenderStatusDot status={project.status} live={project.live} />
        <h2 style={{ margin: 0 }}>{project.name}</h2>
        <span style={{
          fontSize: 11, fontWeight: 600, textTransform: 'uppercase', marginLeft: 4,
          color: renderStatusColor(project.status, project.live),
        }}>
          {project.live ? 'live' : project.status}
        </span>
      </div>

      <div style={{ fontSize: 13, color: 'var(--text-dim)', marginBottom: 20 }}>
        <a href={project.url} target="_blank" rel="noreferrer" style={{ color: 'var(--accent)' }}>{project.url}</a>
        <span style={{ margin: '0 8px' }}>·</span>
        <span>{project.runtime}</span>
        <span style={{ margin: '0 8px' }}>·</span>
        <span>Port {project.port}</span>
      </div>

      <div style={{ display: 'flex', gap: 8, marginBottom: 20 }}>
        <button className="btn-primary" onClick={doDeploy} disabled={deploying}>
          {deploying ? '⏳ Building…' : '🚀 Deploy'}
        </button>
        {(project.live || project.status === 'running') && (
          <button className="btn-sm btn-ghost" onClick={doStop}>⏹ Stop</button>
        )}
        <button className="btn-sm btn-ghost" onClick={doDelete} style={{ color: 'var(--red)' }}>🗑 Delete</button>
        <div style={{ flex: 1 }} />
        <button className="btn-sm btn-ghost" onClick={loadProject}>↻</button>
      </div>

      <div className="render-tabs" style={{
        display: 'flex', gap: 0, borderBottom: '1px solid var(--border)', marginBottom: 20,
      }}>
        {tabs.map(t => (
          <button key={t} onClick={() => setTab(t)} style={{
            background: 'none', border: 'none', color: tab === t ? 'var(--accent)' : 'var(--text-dim)',
            padding: '8px 18px', cursor: 'pointer', fontWeight: tab === t ? 600 : 400,
            borderBottom: tab === t ? '2px solid var(--accent)' : '2px solid transparent',
            fontSize: 14, textTransform: 'capitalize', transition: 'color 0.15s',
          }}>
            {t}
          </button>
        ))}
      </div>

      {tab === 'overview' && <RenderOverviewTab project={project} onUpdate={loadProject} />}
      {tab === 'env' && <RenderEnvTab projectId={projectId} />}
      {tab === 'logs' && <RenderLogsTab projectId={projectId} buildLog={buildLog} />}
      {tab === 'deployments' && <RenderDeploymentsTab projectId={projectId} />}
    </>
  );
}

// ── Overview Tab ─────────────────────────────────────────────────────────

function RenderOverviewTab({ project, onUpdate }) {
  const [buildCmd, setBuildCmd] = useState(project.build_command || 'npm install');
  const [startCmd, setStartCmd] = useState(project.start_command || 'npm start');
  const [runtime, setRuntime] = useState(project.runtime || 'node');
  const [saving, setSaving] = useState(false);
  const [saved, setSaved] = useState(false);

  const doSave = async () => {
    setSaving(true);
    try {
      await api(`/api/render/projects/${project.id}`, {
        method: 'PUT',
        body: JSON.stringify({ build_command: buildCmd, start_command: startCmd, runtime }),
      });
      setSaved(true);
      setTimeout(() => setSaved(false), 2000);
      onUpdate();
    } catch {}
    finally { setSaving(false); }
  };

  return (
    <div style={{ display: 'grid', gap: 20, maxWidth: 640 }}>
      <div className="profile-card" style={{ maxWidth: 'none' }}>
        <h3>Configuration</h3>
        <div style={{ display: 'grid', gap: 14, marginTop: 12 }}>
          <div>
            <label style={labelStyle}>Runtime</label>
            <select value={runtime} onChange={e => setRuntime(e.target.value)}>
              <option value="node">Node.js</option>
              <option value="bun">Bun</option>
            </select>
          </div>
          <div>
            <label style={labelStyle}>Build command</label>
            <input value={buildCmd} onChange={e => setBuildCmd(e.target.value)} placeholder="npm install" />
            <span style={hintStyle}>Runs during each deploy (install deps, compile, etc.)</span>
          </div>
          <div>
            <label style={labelStyle}>Start command</label>
            <input value={startCmd} onChange={e => setStartCmd(e.target.value)} placeholder="npm start" />
            <span style={hintStyle}>Command to start the app (receives PORT env var)</span>
          </div>
          <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
            <button className="btn-primary" onClick={doSave} disabled={saving}>
              {saving ? 'Saving…' : 'Save'}
            </button>
            {saved && <span style={{ color: 'var(--green)', fontSize: 13 }}>✓ Saved</span>}
          </div>
        </div>
      </div>

      <div className="profile-card" style={{ maxWidth: 'none' }}>
        <h3>Info</h3>
        <div style={{ display: 'grid', gridTemplateColumns: 'auto 1fr', gap: '8px 20px', fontSize: 13, marginTop: 8 }}>
          <span style={{ color: 'var(--text-dim)' }}>Project ID</span>
          <code style={codeStyle}>{project.id}</code>
          <span style={{ color: 'var(--text-dim)' }}>Port</span>
          <span>{project.port}</span>
          <span style={{ color: 'var(--text-dim)' }}>Source size</span>
          <span>{formatBytes(project.source_size)}</span>
          <span style={{ color: 'var(--text-dim)' }}>Created</span>
          <span>{new Date(project.created_at).toLocaleString()}</span>
          <span style={{ color: 'var(--text-dim)' }}>Updated</span>
          <span>{new Date(project.updated_at).toLocaleString()}</span>
        </div>
      </div>

      <div className="profile-card" style={{ maxWidth: 'none' }}>
        <h3>Re-upload source</h3>
        <p style={{ fontSize: 13, color: 'var(--text-dim)', marginTop: 4 }}>
          Run this from your project folder to upload new source, then deploy from here:
        </p>
        <pre style={{
          background: 'var(--bg)', border: '1px solid var(--border)', borderRadius: 8,
          padding: 12, fontSize: 12, fontFamily: 'SF Mono,Menlo,Consolas,monospace',
          color: 'var(--accent)', margin: '8px 0 0',
        }}>$ vibey render-init .</pre>
      </div>
    </div>
  );
}

const labelStyle = { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-dim)', marginBottom: 4, textTransform: 'uppercase', letterSpacing: '0.5px' };
const hintStyle = { display: 'block', fontSize: 11, color: 'var(--text-dim)', marginTop: 4 };
const codeStyle = { fontSize: 12, fontFamily: 'SF Mono,Menlo,Consolas,monospace', color: 'var(--text)' };

function formatBytes(bytes) {
  if (!bytes) return '—';
  if (bytes < 1024) return bytes + ' B';
  if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KB';
  return (bytes / 1048576).toFixed(1) + ' MB';
}

// ── Env Tab ─────────────────────────────────────────────────────────────

function RenderEnvTab({ projectId }) {
  const [vars, setVars] = useState([]);
  const [loading, setLoading] = useState(true);
  const [newKey, setNewKey] = useState('');
  const [newVal, setNewVal] = useState('');
  const [adding, setAdding] = useState(false);

  const loadVars = useCallback(async () => {
    setLoading(true);
    try {
      const list = await api(`/api/render/projects/${projectId}/env`);
      setVars(Array.isArray(list) ? list : []);
    } catch { setVars([]); }
    finally { setLoading(false); }
  }, [projectId]);

  useEffect(() => { loadVars(); }, [loadVars]);

  const addVar = async () => {
    if (!newKey.trim()) return;
    setAdding(true);
    try {
      await api(`/api/render/projects/${projectId}/env`, {
        method: 'POST', body: JSON.stringify({ key: newKey.trim(), value: newVal }),
      });
      setNewKey('');
      setNewVal('');
      loadVars();
    } catch {}
    finally { setAdding(false); }
  };

  const removeVar = async (key) => {
    try {
      await api(`/api/render/projects/${projectId}/env/${encodeURIComponent(key)}`, { method: 'DELETE' });
      loadVars();
    } catch {}
  };

  return (
    <div style={{ maxWidth: 700 }}>
      <div className="profile-card" style={{ maxWidth: 'none' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 }}>
          <h3 style={{ margin: 0 }}>Environment Variables</h3>
          <button className="btn-sm btn-ghost" onClick={loadVars} disabled={loading}>↻</button>
        </div>

        <p style={{ fontSize: 12, color: 'var(--text-dim)', marginBottom: 16 }}>
          Env vars are injected at runtime. Redeploy after changes for them to take effect.
        </p>

        {vars.length > 0 && (
          <div style={{ border: '1px solid var(--border)', borderRadius: 8, overflow: 'hidden', marginBottom: 16 }}>
            {vars.map((v, i) => (
              <div key={v.key} style={{
                display: 'flex', alignItems: 'center', padding: '10px 14px', gap: 12,
                borderBottom: i < vars.length - 1 ? '1px solid var(--border)' : 'none',
                background: i % 2 === 0 ? 'transparent' : 'var(--surface-hover)',
              }}>
                <code style={{ fontSize: 13, fontFamily: 'SF Mono,Menlo,Consolas,monospace', fontWeight: 600, minWidth: 140, color: 'var(--accent)' }}>{v.key}</code>
                <code style={{ fontSize: 13, fontFamily: 'SF Mono,Menlo,Consolas,monospace', flex: 1, color: 'var(--text)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{v.value}</code>
                <button className="btn-sm btn-ghost" onClick={() => removeVar(v.key)} style={{ color: 'var(--red)', flexShrink: 0, padding: '4px 8px' }}>✕</button>
              </div>
            ))}
          </div>
        )}

        <div style={{ display: 'flex', gap: 8, alignItems: 'flex-end' }}>
          <div style={{ flex: 1 }}>
            <label style={labelStyle}>Key</label>
            <input value={newKey} onChange={e => setNewKey(e.target.value)} placeholder="DATABASE_URL"
              onKeyDown={e => e.key === 'Enter' && addVar()} />
          </div>
          <div style={{ flex: 2 }}>
            <label style={labelStyle}>Value</label>
            <input value={newVal} onChange={e => setNewVal(e.target.value)} placeholder="postgres://..."
              onKeyDown={e => e.key === 'Enter' && addVar()} />
          </div>
          <button className="btn-primary" onClick={addVar} disabled={adding} style={{ height: 42, flexShrink: 0 }}>
            {adding ? '…' : '+ Add'}
          </button>
        </div>
      </div>
    </div>
  );
}

// ── Logs Tab ────────────────────────────────────────────────────────────

function RenderLogsTab({ projectId, buildLog }) {
  const [log, setLog] = useState('');
  const [loading, setLoading] = useState(true);
  const logRef = useRef(null);

  const loadLogs = useCallback(async () => {
    setLoading(true);
    try {
      const data = await api(`/api/render/projects/${projectId}/logs?lines=300`);
      setLog(data.log || '');
    } catch { setLog(''); }
    finally { setLoading(false); }
  }, [projectId]);

  useEffect(() => { loadLogs(); }, [loadLogs]);
  useEffect(() => {
    if (logRef.current) logRef.current.scrollTop = logRef.current.scrollHeight;
  }, [log, buildLog]);

  const combined = [buildLog, log].filter(Boolean).join('\n---\n');

  return (
    <div className="profile-card" style={{ maxWidth: 'none' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
        <h3 style={{ margin: 0 }}>Logs</h3>
        <button className="btn-sm btn-ghost" onClick={loadLogs} disabled={loading}>↻ Refresh</button>
      </div>
      <div ref={logRef} style={{
        background: '#0d1117', border: '1px solid var(--border)', borderRadius: 8,
        padding: 16, fontFamily: 'SF Mono,Menlo,Consolas,monospace', fontSize: 12,
        color: '#c9d1d9', whiteSpace: 'pre-wrap', wordBreak: 'break-all',
        maxHeight: 500, overflowY: 'auto', lineHeight: 1.6,
      }}>
        {combined || (loading ? 'Loading…' : 'No logs yet. Deploy the project to generate logs.')}
      </div>
    </div>
  );
}

// ── Deployments Tab ─────────────────────────────────────────────────────

function RenderDeploymentsTab({ projectId }) {
  const [deploys, setDeploys] = useState([]);
  const [loading, setLoading] = useState(true);

  const load = useCallback(async () => {
    setLoading(true);
    try {
      const list = await api(`/api/render/projects/${projectId}/deployments`);
      setDeploys(Array.isArray(list) ? list : []);
    } catch { setDeploys([]); }
    finally { setLoading(false); }
  }, [projectId]);

  useEffect(() => { load(); }, [load]);

  return (
    <div className="profile-card" style={{ maxWidth: 'none' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
        <h3 style={{ margin: 0 }}>Deployment History</h3>
        <button className="btn-sm btn-ghost" onClick={load} disabled={loading}>↻</button>
      </div>

      {!loading && deploys.length === 0 && (
        <p style={{ color: 'var(--text-dim)' }}>No deployments yet.</p>
      )}

      {deploys.length > 0 && (
        <div style={{ border: '1px solid var(--border)', borderRadius: 8, overflow: 'hidden' }}>
          {deploys.map((d, i) => {
            const statusColor = d.status === 'live' ? 'var(--green)' : d.status === 'failed' ? 'var(--red)' : d.status === 'building' ? 'var(--yellow)' : 'var(--text-dim)';
            return (
              <div key={d.id} style={{
                display: 'flex', alignItems: 'center', padding: '10px 14px', gap: 14,
                borderBottom: i < deploys.length - 1 ? '1px solid var(--border)' : 'none',
                background: i % 2 === 0 ? 'transparent' : 'var(--surface-hover)',
              }}>
                <span style={{ width: 8, height: 8, borderRadius: '50%', background: statusColor, flexShrink: 0 }} />
                <span style={{ fontSize: 12, fontFamily: 'SF Mono,Menlo,Consolas,monospace', color: 'var(--text-dim)', minWidth: 30 }}>#{d.id}</span>
                <span style={{ fontSize: 12, fontWeight: 600, color: statusColor, textTransform: 'uppercase', minWidth: 70 }}>{d.status}</span>
                <span style={{ fontSize: 12, color: 'var(--text-dim)' }}>{d.trigger_source}</span>
                <div style={{ flex: 1 }} />
                <span style={{ fontSize: 12, color: 'var(--text-dim)' }}>
                  {new Date(d.created_at).toLocaleString()}
                </span>
                {d.finished_at && (
                  <span style={{ fontSize: 11, color: 'var(--text-dim)' }}>
                    ({Math.round((new Date(d.finished_at) - new Date(d.created_at)) / 1000)}s)
                  </span>
                )}
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}
