// ─────────────────────────────────────────────
// DEV_AppDetail_Logs.jsx
// Log viewer for an app — access, dev, admin, user events
//
// Loaded in: do-dev/index.html  (before DEV_AppDetail.jsx)
// Used by:   DEV_AppDetail.jsx  as:
//   {tab === 'logs' && <DEVLogs app={app} />}
// ─────────────────────────────────────────────

// ─────────────────────────────────────────────
// IpLookupModal
// Calls /v6/dev/iplookup?ip=x.x.x.x which hits
// ipstack via the server (keeps API key private)
// ─────────────────────────────────────────────
function IpLookupModal({ ip, onClose }) {
  const [data,    setData]    = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const [error,   setError]   = React.useState(null);

  React.useEffect(() => {
    apiFetch(`${API_BASE}/v6/dev/iplookup?ip=${encodeURIComponent(ip)}`)
      .then(r => r.json())
      .then(d => {
        if (d.status !== 'ok') throw new Error(d.message);
        setData(d.result);
      })
      .catch(e => setError(e.message))
      .finally(() => setLoading(false));

    // Close on Escape
    function onKey(e) { if (e.key === 'Escape') onClose(); }
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [ip]);

  const mapsUrl = data?.latitude && data?.longitude
    ? `https://www.google.com/maps?q=${data.latitude},${data.longitude}`
    : null;

  return (
    <div style={SLog.modalOverlay} onClick={e => { if (e.target === e.currentTarget) onClose(); }}>
      <div style={SLog.modal}>
        {/* Header */}
        <div style={SLog.modalHeader}>
          <div>
            <div style={{ fontSize:13, fontWeight:700, color:'#0f1923' }}>IP Lookup</div>
            <div style={{ fontSize:12, fontFamily:'DM Mono, monospace', color:'#2563eb', marginTop:2 }}>{ip}</div>
          </div>
          <button onClick={onClose} style={SLog.modalClose}>✕</button>
        </div>

        {loading && (
          <div style={{ padding:'40px 0', textAlign:'center', color:'#94a3b8', fontSize:13 }}>
            Looking up {ip}…
          </div>
        )}

        {error && (
          <div style={{ padding:'20px', background:'#fef2f2', color:'#dc2626',
                        borderRadius:8, fontSize:13, margin:'16px 0' }}>
            {error}
          </div>
        )}

        {data && !loading && (
          <div>
            {/* Location summary */}
            <div style={{ fontSize:22, textAlign:'center', padding:'16px 0 8px' }}>
              {data.country_flag_emoji || '🌐'}
            </div>
            <div style={{ textAlign:'center', marginBottom:20 }}>
              <div style={{ fontSize:16, fontWeight:700, color:'#0f1923' }}>
                {[data.city, data.region_name, data.country_name].filter(Boolean).join(', ')}
              </div>
              <div style={{ fontSize:12, color:'#94a3b8', marginTop:4 }}>
                {data.zip && `ZIP ${data.zip}`}
                {data.zip && data.time_zone_id && ' · '}
                {data.time_zone_id}
              </div>
            </div>

            {/* Detail grid */}
            <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:10, marginBottom:16 }}>
              {[
                ['IP',           data.ip],
                ['Type',         data.type || '—'],
                ['Country',      `${data.country_name} (${data.country_code})`],
                ['Region',       `${data.region_name} (${data.region_code})`],
                ['City',         data.city || '—'],
                ['ZIP',          data.zip  || '—'],
                ['Continent',    data.continent_name || '—'],
                ['Timezone',     data.time_zone_id   || '—'],
                ['ISP',          data.connection_isp  || '—'],
                ['Org Type',     data.connection_type || '—'],
                ['Lat/Lon',      data.latitude && data.longitude
                                   ? `${Number(data.latitude).toFixed(4)}, ${Number(data.longitude).toFixed(4)}`
                                   : '—'],
                ['Connection',   data.ip_routing_type || '—'],
              ].map(([k, v]) => (
                <div key={k} style={SLog.expandedField}>
                  <div style={SLog.expandedKey}>{k}</div>
                  <div style={{ ...SLog.expandedVal, fontFamily:'DM Sans, sans-serif', fontSize:12 }}>
                    {String(v ?? '—')}
                  </div>
                </div>
              ))}
            </div>

            {/* Map link */}
            {mapsUrl && (
              <a href={mapsUrl} target="_blank" rel="noopener"
                style={{ display:'block', textAlign:'center', color:'#2563eb',
                         fontSize:13, fontWeight:500, textDecoration:'none',
                         padding:'10px', background:'#eff6ff', borderRadius:8 }}>
                🗺 View on Google Maps
              </a>
            )}
          </div>
        )}
      </div>
    </div>
  );
}

function DEVLogs({ app }) {
  const PAGE = 50;

  const [logs,       setLogs]       = React.useState([]);
  const [total,      setTotal]      = React.useState(0);
  const [loading,    setLoading]    = React.useState(true);
  const [error,      setError]      = React.useState(null);
  const [offset,     setOffset]     = React.useState(0);
  const [typeFilter, setTypeFilter] = React.useState('');
  const [expanded,   setExpanded]   = React.useState(null);
  const [ipModal,    setIpModal]    = React.useState(null); // IP string to look up

  function fetchLogs(off = 0, type = typeFilter) {
    setLoading(true); setError(null);
    let url = `${API_BASE}/v6/dev/logs?app=${app.app_id}&limit=${PAGE}&offset=${off}`;
    if (type) url += `&type=${type}`;
    apiFetch(url)
      .then(r => r.json())
      .then(data => {
        if (data.status !== 'ok') throw new Error(data.message);
        setLogs(data.logs || []);
        setTotal(data.total || 0);
        setOffset(off);
      })
      .catch(e => setError(e.message))
      .finally(() => setLoading(false));
  }

  React.useEffect(() => { fetchLogs(0, typeFilter); }, [app.app_id]);

  function handleTypeChange(t) {
    setTypeFilter(t);
    setOffset(0);
    fetchLogs(0, t);
  }

  const TYPE_COLORS = {
    access: { bg:'#eff6ff', color:'#2563eb' },
    dev:    { bg:'#f0fdf4', color:'#059669' },
    admin:  { bg:'#fef3c7', color:'#d97706' },
    user:   { bg:'#faf5ff', color:'#7c3aed' },
  };

  function typeBadge(type) {
    const c = TYPE_COLORS[type] || { bg:'#f1f5f9', color:'#64748b' };
    return (
      <span style={{ ...SLog.badge, background:c.bg, color:c.color }}>
        {type || 'unknown'}
      </span>
    );
  }

  function parseLogData(raw) {
    try { return JSON.parse(raw || '{}'); } catch(e) { return {}; }
  }

  function formatRelative(d) {
    if (!d) return '—';
    const diff = Date.now() - new Date(d).getTime();
    const m = Math.floor(diff / 60000);
    if (m < 1)  return 'just now';
    if (m < 60) return `${m}m ago`;
    const h = Math.floor(m / 60);
    if (h < 24) return `${h}h ago`;
    const dy = Math.floor(h / 24);
    if (dy < 7) return `${dy}d ago`;
    return new Date(d).toLocaleDateString('en-US', { month:'short', day:'numeric' });
  }

  function formatFull(d) {
    if (!d) return '—';
    return new Date(d).toLocaleString('en-US', {
      month:'short', day:'numeric', year:'numeric',
      hour:'2-digit', minute:'2-digit', second:'2-digit',
    });
  }

  const hasPrev = offset > 0;
  const hasNext = offset + PAGE < total;

  return (
    <div>
      {/* ── Filter bar ── */}
      <div style={SLog.filterBar}>
        <div style={{ display:'flex', gap:6 }}>
          {['', 'access', 'dev', 'admin', 'user'].map(t => (
            <button key={t} onClick={() => handleTypeChange(t)}
              style={{
                ...SLog.filterBtn,
                background: typeFilter === t ? '#0f1923' : '#f1f5f9',
                color:      typeFilter === t ? '#fff'    : '#374151',
              }}>
              {t === '' ? 'All' : t.charAt(0).toUpperCase() + t.slice(1)}
            </button>
          ))}
        </div>
        <div style={{ display:'flex', alignItems:'center', gap:12 }}>
          <span style={{ fontSize:12, color:'#94a3b8' }}>
            {loading ? 'Loading…' : `${total.toLocaleString()} entries`}
          </span>
          <button onClick={() => fetchLogs(offset)} style={SLog.refreshBtn}>↻ Refresh</button>
        </div>
      </div>

      {error && <div style={SLog.error}>{error}</div>}

      {/* ── Log table ── */}
      <div style={SLog.tableWrap}>
        {/* Header */}
        <div style={SLog.headerRow}>
          <span style={{ flex:1.2 }}>Time</span>
          <span style={{ width:72 }}>Type</span>
          <span style={{ flex:2 }}>User</span>
          <span style={{ flex:1.5 }}>IP</span>
          <span style={{ flex:2 }}>Location</span>
          <span style={{ flex:1 }}>Action</span>
          <span style={{ width:32 }} />
        </div>

        {loading && (
          <div style={{ padding:'40px 0', textAlign:'center', color:'#94a3b8', fontSize:13 }}>
            Loading logs…
          </div>
        )}

        {!loading && logs.length === 0 && (
          <div style={{ padding:'40px 0', textAlign:'center', color:'#94a3b8', fontSize:13 }}>
            No log entries found.
          </div>
        )}

        {!loading && logs.map(log => {
          const data   = parseLogData(log.log_data);
          const isOpen = expanded === log.log_id;
          const mapsUrl = log.log_ip
            ? `https://www.google.com/maps/search/${encodeURIComponent(data.location || log.log_ip)}`
            : null;

          return (
            <div key={log.log_id}>
              {/* ── Main row ── */}
              <div style={{ ...SLog.dataRow, background: isOpen ? '#f8fafc' : '#fff' }}>
                <div style={{ flex:1.2 }}>
                  <div style={SLog.timeMain} title={formatFull(log.log_date_insert)}>
                    {formatRelative(log.log_date_insert)}
                  </div>
                  <div style={SLog.timeSub}>{formatFull(log.log_date_insert).split(',').slice(0,2).join(',')}</div>
                </div>
                <div style={{ width:72 }}>{typeBadge(log.log_type)}</div>
                <div style={{ flex:2 }}>
                  <div style={SLog.userEmail}>{data.email || '—'}</div>
                  {log.log_user && <div style={SLog.userId}>{log.log_user?.slice(0,8)}…</div>}
                </div>
                <div style={{ flex:1.5, display:'flex', alignItems:'center', gap:6 }}>
                  <div style={SLog.ip}>{log.log_ip || '—'}</div>
                  {log.log_ip && log.log_ip !== '::ffff:127.0.0.1' && log.log_ip !== '127.0.0.1' && (
                    <button
                      onClick={() => setIpModal(log.log_ip)}
                      title="Look up IP location"
                      style={{ background:'none', border:'none', cursor:'pointer',
                               color:'#2563eb', fontSize:12, padding:'2px 4px',
                               borderRadius:4, lineHeight:1 }}>
                      🔍
                    </button>
                  )}
                </div>
                <div style={{ flex:2 }}>
                  {data.location
                    ? (
                      <div style={{ display:'flex', alignItems:'center', gap:6 }}>
                        <span style={SLog.location}>{data.location}</span>
                        {mapsUrl && (
                          <a href={mapsUrl} target="_blank" rel="noopener"
                            style={{ fontSize:10, color:'#2563eb', textDecoration:'none' }}
                            title="View on map">
                            🗺
                          </a>
                        )}
                      </div>
                    )
                    : <span style={{ color:'#94a3b8', fontSize:12 }}>—</span>
                  }
                </div>
                <div style={{ flex:1 }}>
                  <span style={SLog.action}>{data.action || '—'}</span>
                </div>
                <div style={{ width:32 }}>
                  <button
                    onClick={() => setExpanded(isOpen ? null : log.log_id)}
                    style={SLog.expandBtn}
                    title={isOpen ? 'Collapse' : 'Expand'}>
                    {isOpen ? '▲' : '▼'}
                  </button>
                </div>
              </div>

              {/* ── Expanded detail ── */}
              {isOpen && (
                <div style={SLog.expandedRow}>
                  <div style={SLog.expandedGrid}>
                    {[
                      ['Log ID',    log.log_id],
                      ['Date/Time', formatFull(log.log_date_insert)],
                      ['Type',      log.log_type],
                      ['IP',        log.log_ip],
                      ['User ID',   log.log_user],
                      ['Location',  data.location || '—'],
                      ['City',      data.city || '—'],
                      ['Region',    data.region_name || '—'],
                      ['Country',   data.country_name || '—'],
                      ['Action',    data.action || '—'],
                      ...(log.log_table  ? [['Table',  log.log_table]]  : []),
                      ...(log.log_record ? [['Record', log.log_record]] : []),
                      ...(log.log_field  ? [['Field',  log.log_field]]  : []),
                    ].map(([k, v]) => (
                      <div key={k} style={SLog.expandedField}>
                        <div style={SLog.expandedKey}>{k}</div>
                        <div style={SLog.expandedVal}>{String(v ?? '—')}</div>
                      </div>
                    ))}
                  </div>
                  <div style={{ marginTop:12 }}>
                    <div style={SLog.expandedKey}>Raw JSON</div>
                    <pre style={SLog.pre}>{JSON.stringify(data, null, 2)}</pre>
                  </div>
                </div>
              )}
            </div>
          );
        })}
      </div>

      {/* ── Pagination ── */}
      {total > PAGE && (
        <div style={SLog.pagination}>
          <button onClick={() => fetchLogs(0)}            disabled={!hasPrev} style={SLog.pageBtn}>«</button>
          <button onClick={() => fetchLogs(offset - PAGE)} disabled={!hasPrev} style={SLog.pageBtn}>‹ Prev</button>
          <span style={{ fontSize:12, color:'#64748b' }}>
            {offset + 1}–{Math.min(offset + PAGE, total)} of {total.toLocaleString()}
          </span>
          <button onClick={() => fetchLogs(offset + PAGE)} disabled={!hasNext} style={SLog.pageBtn}>Next ›</button>
          <button onClick={() => fetchLogs(Math.floor((total - 1) / PAGE) * PAGE)} disabled={!hasNext} style={SLog.pageBtn}>»</button>
        </div>
      )}

      {/* ── IP Lookup Modal ── */}
      {ipModal && (
        <IpLookupModal ip={ipModal} onClose={() => setIpModal(null)} />
      )}
    </div>
  );
}

// ── Styles ───────────────────────────────────
const SLog = {
  filterBar:    { display:'flex', alignItems:'center', justifyContent:'space-between',
                  marginBottom:16, flexWrap:'wrap', gap:8 },
  filterBtn:    { padding:'6px 14px', borderRadius:20, border:'none', fontSize:12, fontWeight:500,
                  cursor:'pointer', fontFamily:'DM Sans, sans-serif', transition:'background 0.15s' },
  refreshBtn:   { padding:'5px 12px', background:'none', border:'1.5px solid #e2e8f0', borderRadius:7,
                  fontSize:12, cursor:'pointer', color:'#374151', fontFamily:'DM Sans, sans-serif' },
  tableWrap:    { border:'1px solid #e2e8f0', borderRadius:10, overflow:'hidden', background:'#fff' },
  headerRow:    { display:'flex', alignItems:'center', gap:12, padding:'10px 16px',
                  background:'#f8fafc', fontSize:11, fontWeight:700, color:'#64748b',
                  textTransform:'uppercase', letterSpacing:'0.05em', borderBottom:'1px solid #e2e8f0' },
  dataRow:      { display:'flex', alignItems:'center', gap:12, padding:'10px 16px',
                  borderBottom:'1px solid #f1f5f9', transition:'background 0.1s' },
  timeMain:     { fontSize:12, fontWeight:600, color:'#374151' },
  timeSub:      { fontSize:11, color:'#94a3b8' },
  userEmail:    { fontSize:13, fontWeight:500, color:'#0f1923' },
  userId:       { fontSize:11, color:'#94a3b8', fontFamily:'DM Mono, monospace' },
  ip:           { fontSize:12, fontFamily:'DM Mono, monospace', color:'#374151' },
  location:     { fontSize:12, color:'#374151' },
  action:       { fontSize:12, color:'#64748b' },
  badge:        { padding:'3px 8px', borderRadius:20, fontSize:11, fontWeight:600 },
  expandBtn:    { background:'none', border:'none', color:'#94a3b8', cursor:'pointer',
                  fontSize:11, padding:'3px 6px', borderRadius:4, fontFamily:'DM Sans, sans-serif' },
  expandedRow:  { padding:'16px 20px', background:'#f8fafc', borderBottom:'1px solid #e2e8f0' },
  expandedGrid: { display:'grid', gridTemplateColumns:'repeat(auto-fill, minmax(200px, 1fr))', gap:10 },
  expandedField:{ background:'#fff', border:'1px solid #e2e8f0', borderRadius:7, padding:'8px 12px' },
  expandedKey:  { fontSize:10, fontWeight:700, color:'#94a3b8', textTransform:'uppercase',
                  letterSpacing:'0.05em', marginBottom:3 },
  expandedVal:  { fontSize:12, color:'#0f1923', fontFamily:'DM Mono, monospace', wordBreak:'break-all' },
  pre:          { fontSize:11, color:'#374151', background:'#f1f5f9', padding:'10px 14px',
                  borderRadius:7, marginTop:6, overflowX:'auto', lineHeight:1.5,
                  fontFamily:'DM Mono, monospace' },
  pagination:   { display:'flex', alignItems:'center', justifyContent:'center', gap:8, marginTop:16 },
  pageBtn:      { padding:'6px 12px', background:'#fff', border:'1.5px solid #e2e8f0', borderRadius:7,
                  fontSize:12, cursor:'pointer', fontFamily:'DM Sans, sans-serif', color:'#374151',
                  transition:'border-color 0.15s' },
  error:        { background:'#fef2f2', color:'#dc2626', padding:'10px 14px', borderRadius:8,
                  fontSize:12, marginBottom:12, border:'1px solid #fecaca' },
  modalOverlay: { position:'fixed', inset:0, background:'rgba(0,0,0,0.45)', zIndex:1000,
                  display:'flex', alignItems:'center', justifyContent:'center', padding:20 },
  modal:        { background:'#fff', borderRadius:14, padding:'24px', width:'100%', maxWidth:480,
                  maxHeight:'90vh', overflowY:'auto',
                  boxShadow:'0 20px 60px rgba(0,0,0,0.2)' },
  modalHeader:  { display:'flex', alignItems:'flex-start', justifyContent:'space-between',
                  marginBottom:16, paddingBottom:14, borderBottom:'1px solid #f1f5f9' },
  modalClose:   { background:'none', border:'none', color:'#94a3b8', cursor:'pointer',
                  fontSize:18, padding:'0 4px', lineHeight:1, fontFamily:'DM Sans, sans-serif' },
};
