/**
 * history.js — Job history panel for Timmy Tower Workshop.
 *
 * Persists completed jobs in localStorage and renders them in a
 * bottom-sheet panel with expandable results and pull-to-refresh.
 *
 * Public API:
 *   addHistoryEntry(entry)   — called by payment.js / session.js on completion
 *   initHistoryPanel()       — wire up DOM (call once from main.js)
 */

const LS_KEY      = 'timmy_history_v1';
const MAX_ENTRIES = 50;

// ── Persistence ───────────────────────────────────────────────────────────────

function _loadEntries() {
  try {
    const raw = localStorage.getItem(LS_KEY);
    return raw ? JSON.parse(raw) : [];
  } catch {
    return [];
  }
}

function _saveEntries(entries) {
  try {
    localStorage.setItem(LS_KEY, JSON.stringify(entries));
  } catch { /* storage full — oldest already trimmed */ }
}

/**
 * Record a completed job.
 * @param {object} entry
 * @param {string} entry.jobId
 * @param {string} entry.request      — user prompt
 * @param {number} entry.costSats     — sats charged (0 for free/session)
 * @param {string} entry.result       — AI answer or rejection reason
 * @param {string} entry.state        — 'complete' | 'rejected' | 'failed'
 * @param {string} [entry.completedAt] — ISO timestamp (defaults to now)
 */
export function addHistoryEntry({ jobId, request, costSats, result, state, completedAt }) {
  const entries = _loadEntries();
  const entry = {
    jobId:       jobId       ?? `local-${Date.now()}`,
    request:     request     ?? '',
    costSats:    costSats    ?? 0,
    result:      result      ?? '',
    state:       state       ?? 'complete',
    completedAt: completedAt ?? new Date().toISOString(),
  };
  const idx = entries.findIndex(e => e.jobId === entry.jobId);
  if (idx >= 0) {
    entries[idx] = entry;
  } else {
    entries.unshift(entry); // newest first
    if (entries.length > MAX_ENTRIES) entries.length = MAX_ENTRIES;
  }
  _saveEntries(entries);
}

// ── Helpers ───────────────────────────────────────────────────────────────────

function _relativeTime(isoString) {
  try {
    const diff = Date.now() - new Date(isoString).getTime();
    const secs = Math.floor(diff / 1000);
    if (secs < 60)  return `${secs}s ago`;
    const mins = Math.floor(secs / 60);
    if (mins < 60)  return `${mins} min ago`;
    const hrs  = Math.floor(mins / 60);
    if (hrs  < 24)  return `${hrs}h ago`;
    const days = Math.floor(hrs  / 24);
    return `${days}d ago`;
  } catch {
    return '';
  }
}

function _escHtml(text) {
  return String(text)
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;');
}

function _truncate(text, maxLen) {
  if (!text) return '';
  return text.length > maxLen ? text.slice(0, maxLen) + '…' : text;
}

// ── Rendering ─────────────────────────────────────────────────────────────────

function _renderEntries(entries, container) {
  container.innerHTML = '';

  if (!entries.length) {
    const empty = document.createElement('div');
    empty.className = 'hist-empty';
    empty.textContent = 'No completed jobs yet. Submit a job to see your history here.';
    container.appendChild(empty);
    return;
  }

  entries.forEach(entry => {
    const row = document.createElement('div');
    row.className = 'hist-row' + (entry.state === 'rejected' ? ' hist-rejected' : '');

    // ── Header (always visible) ────────────────────────────────────────────
    const header = document.createElement('div');
    header.className = 'hist-row-header';

    const promptEl = document.createElement('div');
    promptEl.className = 'hist-prompt';
    promptEl.textContent = _truncate(entry.request, 140);

    const metaEl = document.createElement('div');
    metaEl.className = 'hist-meta';

    const costEl = document.createElement('span');
    costEl.className = 'hist-cost';
    if (entry.state === 'rejected') {
      costEl.textContent = 'rejected';
    } else if (entry.costSats > 0) {
      costEl.textContent = `⚡ ${entry.costSats} sats`;
    } else {
      costEl.textContent = 'free';
    }

    const timeEl = document.createElement('span');
    timeEl.className = 'hist-time';
    timeEl.textContent = _relativeTime(entry.completedAt);

    const chevronEl = document.createElement('span');
    chevronEl.className = 'hist-chevron';
    chevronEl.textContent = '▸';

    metaEl.appendChild(costEl);
    metaEl.appendChild(timeEl);
    metaEl.appendChild(chevronEl);

    header.appendChild(promptEl);
    header.appendChild(metaEl);

    // ── Body (expandable) ──────────────────────────────────────────────────
    const body = document.createElement('div');
    body.className = 'hist-row-body';

    const pre = document.createElement('pre');
    pre.className = 'hist-result';
    pre.textContent = entry.result || '(no result)';
    body.appendChild(pre);

    // ── Toggle ─────────────────────────────────────────────────────────────
    let expanded = false;
    header.addEventListener('click', () => {
      expanded = !expanded;
      row.classList.toggle('expanded', expanded);
      chevronEl.textContent = expanded ? '▾' : '▸';
    });

    row.appendChild(header);
    row.appendChild(body);
    container.appendChild(row);
  });
}

// ── Panel state ───────────────────────────────────────────────────────────────

let _panel      = null;
let _list       = null;
let _refreshBtn = null;

function _open() {
  if (!_panel) return;
  _panel.classList.add('open');
  _refresh();
}

function _close() {
  _panel?.classList.remove('open');
}

function _refresh() {
  if (!_list) return;
  const entries = _loadEntries();
  _renderEntries(entries, _list);
  if (_refreshBtn) {
    _refreshBtn.textContent = '↺ REFRESH';
    _refreshBtn.disabled = false;
  }
}

export function initHistoryPanel() {
  _panel      = document.getElementById('history-panel');
  _list       = document.getElementById('history-list');
  _refreshBtn = document.getElementById('history-refresh-btn');
  if (!_panel) return;

  document.getElementById('open-history-btn')?.addEventListener('click', _open);
  document.getElementById('history-close')?.addEventListener('click', _close);

  if (_refreshBtn) {
    _refreshBtn.addEventListener('click', () => {
      _refreshBtn.textContent = '↺ …';
      _refreshBtn.disabled = true;
      setTimeout(_refresh, 150);
    });
  }

  // Pull-to-refresh: detect downward drag when already scrolled to top
  let _touchStartY = 0;
  _list?.addEventListener('touchstart', e => {
    _touchStartY = e.touches[0].clientY;
  }, { passive: true });
  _list?.addEventListener('touchend', e => {
    const dy = e.changedTouches[0].clientY - _touchStartY;
    if (dy > 60 && _list.scrollTop === 0) {
      _refresh();
    }
  }, { passive: true });
}
