/* ═══════════════════════════════════════════════════════════
   FICTION IGNITION — app.js
   Prompt generation, tier gating, history, weekly, exports
   Requires: auth.js loaded first
═══════════════════════════════════════════════════════════ */

'use strict';

// ── Genre labels ─────────────────────────────────────────
const GENRE_LABELS = {
  'literary-fiction':  'Literary Fiction',
  'fantasy':           'Fantasy',
  'science-fiction':   'Science Fiction',
  'horror':            'Horror',
  'mystery':           'Mystery & Thriller',
  'romance':           'Romance',
  'historical-fiction':'Historical Fiction',
  'adventure':         'Adventure',
  'crime':             'Crime & Noir',
  'magical-realism':   'Magical Realism',
  'dystopian':         'Dystopian',
  'comedy':            'Comedy & Satire',
  'western':           'Western',
  'young-adult':       'Young Adult',
  'childrens':         "Children's Story",
};

// Demo prompts (replace callGenerateAPI with real backend)
const DEMO_PROMPTS = {
  'Literary Fiction':    'After her mother\'s death, a woman begins receiving pocket-sized objects in the mail — ordinary things her mother apparently posted years in advance, each arriving on the day it would mean the most.',
  'Fantasy':             'An apprentice mapmaker discovers that the enchanted ink she uses to draw borders physically reshapes the land it depicts — and someone is paying her to redraw an entire kingdom out of existence.',
  'Science Fiction':     'Earth receives a message from a probe launched 200 years ago. The signal contains a warning written in a language that won\'t be invented for another century.',
  'Horror':              'Every night at 3:12 a.m., your smoke detector beeps once. You replaced the battery. You removed the detector entirely. The beeping continued, coming from the exact same spot on the ceiling.',
  'Mystery & Thriller':  'A forensic accountant hired to audit a deceased billionaire\'s estate discovers that for the last decade of his life, someone was secretly paying him a salary — from his own account.',
  'Romance':             'Two rival antique dealers both bid on a mysterious locked box at auction, split the cost to open it together, and find inside a lifetime of love letters addressed to both of their grandmothers.',
  'Historical Fiction':  'A translator at the 1919 Paris Peace Conference realizes she alone holds the key to a mistranslation that, if corrected, would prevent a future war — but correcting it would expose her double identity.',
  'Adventure':           'A retired deep-sea salvage diver is pulled back for one last job: recovering a wreck that, according to her own dive logs from thirty years ago, she has already recovered.',
  'Crime & Noir':        'A private detective hired to find a missing painting discovers it was never stolen — it was hidden by the artist himself to prevent it from revealing a truth he buried with him.',
  'Magical Realism':     'In a small coastal town, grief physically manifests as weight. The recently bereaved sink slightly into the earth when they walk, and the town\'s oldest widow has not left the ground floor in forty years.',
  'Dystopian':           'In a society where memories can be taxed, the poorest citizens sell everything before age thirty — except one woman who discovers a black market memory no one has paid to forget.',
  'Comedy & Satire':     'A professional mourner — hired to cry at strangers\' funerals — accidentally attends the wrong service, becomes the most beloved person in the room, and is named in the will.',
  'Western':             'The most feared gunslinger in the territory has been dead for six years. Someone has been committing crimes in her name ever since — someone who shoots left-handed, just like she did.',
  'Young Adult':         'On the first day of senior year, you discover that the journal you\'ve been writing in for three years has been answering back — in handwriting that isn\'t yours.',
  "Children's Story":    'A young girl discovers her shadow has been sneaking out at night to finish the books she falls asleep reading, and now it knows the endings to stories she hasn\'t read yet.',
};

// ── State ─────────────────────────────────────────────────
let currentPrompt  = null;
let weeklyPrompts  = [];
let promptHistory  = JSON.parse(localStorage.getItem('fi_history') || '[]');

// ── DOM refs ──────────────────────────────────────────────
const genreSelect       = () => document.getElementById('genre-select');
const generateBtn       = () => document.getElementById('generate-btn');
const generateBtnLabel  = () => document.getElementById('generate-btn-label');
const resultArea        = () => document.getElementById('result-area');
const resultIdle        = () => document.getElementById('result-idle');
const resultLoading     = () => document.getElementById('result-loading');
const resultOutput      = () => document.getElementById('result-output');
const resultError       = () => document.getElementById('result-error');
const outputPrompt      = () => document.getElementById('output-prompt');
const outputGenrePill   = () => document.getElementById('output-genre-pill');
const outputMeta        = () => document.getElementById('output-meta');
const errorMsg          = () => document.getElementById('error-msg');
const errorUpgradeLink  = () => document.getElementById('error-upgrade-link');
const adBanner          = () => document.getElementById('ad-banner');
const historySection    = () => document.getElementById('history-section');
const historyListEl     = () => document.getElementById('history-list');
const sidebarTierBadge  = () => document.getElementById('sidebar-tier-badge');
const splanUsed         = () => document.getElementById('splan-used');
const splanLimit        = () => document.getElementById('splan-limit');
const splanFill         = () => document.getElementById('splan-meter-fill');
const splanMeterWrap    = () => document.getElementById('splan-meter-wrap');
const splanUpgradeLink  = () => document.getElementById('splan-upgrade-link');
const weeklyCard        = () => document.getElementById('weekly-card');
const weeklyTbody       = () => document.getElementById('weekly-tbody');
const customGenreGroup  = () => document.getElementById('custom-genre-group');
const sidebarAuthNudge  = () => document.getElementById('sidebar-auth-nudge');

// ── Init ──────────────────────────────────────────────────
document.addEventListener('DOMContentLoaded', () => {
  updateAppState();
  renderHistory();

  genreSelect()?.addEventListener('change', () => {
    const btn = generateBtn();
    if (btn) btn.disabled = !genreSelect().value;
  });
});

// Called by shared.js after successful auth
function onAuthSuccess(user) {
  updateAppState();
  renderHistory();
}

// ── Update all app UI based on current auth/tier ──────────
function updateAppState() {
  const tier     = Auth.tier;
  const info     = Auth.tierInfo;
  const isLoggedIn = Auth.isLoggedIn;
  const left     = Auth.promptsLeft();
  const limit    = info.dailyLimit;

  // Sidebar tier badge
  const badge = sidebarTierBadge();
  if (badge) {
    badge.className = `fi-tier-badge on-light tier-${tier}`;
    badge.textContent = info.label;
  }

  // Usage meter
  if (isLoggedIn) {
    const used  = limit === Infinity ? 0 : Math.max(0, limit - left);
    const pct   = limit === Infinity ? 0 : Math.round((used / limit) * 100);
    const lu    = splanUpgradeLink();
    splanUsed()?.textContent && (splanUsed().textContent = limit === Infinity ? '∞' : String(used));
    splanLimit()?.textContent && (splanLimit().textContent = limit === Infinity ? '∞' : String(limit));
    if (splanFill()) splanFill().style.width = pct + '%';
    if (lu) lu.classList.toggle('hidden', tier === 'author_pro');
    splanMeterWrap()?.style && (splanMeterWrap().style.display = limit === Infinity ? 'none' : 'block');
  } else {
    if (splanUsed())  splanUsed().textContent  = '—';
    if (splanLimit()) splanLimit().textContent = '—';
    if (splanFill())  splanFill().style.width  = '0%';
  }

  // Ad banner
  if (adBanner()) adBanner().style.display = (isLoggedIn && !info.adFree) || !isLoggedIn ? 'block' : 'none';

  // History section
  if (historySection()) historySection().style.display = info.history ? 'block' : 'none';

  // Custom genre
  if (customGenreGroup()) customGenreGroup().style.display = info.customGenre ? 'block' : 'none';

  // Auth nudge
  if (sidebarAuthNudge()) sidebarAuthNudge().style.display = isLoggedIn ? 'none' : 'block';
}

// ── Generate prompt ───────────────────────────────────────
document.addEventListener('DOMContentLoaded', () => {
  generateBtn()?.addEventListener('click', handleGenerate);
});

async function handleGenerate() {
  const genre = genreSelect()?.value;
  if (!genre) return;

  // ── Tier/limit check ─────────────────────────────────
  if (!Auth.canGenerate()) {
    const tier = Auth.tier;
    const limit = Auth.tierInfo.dailyLimit;
    showResult('error');
    if (errorMsg()) errorMsg().textContent = Auth.isLoggedIn
      ? `You've used all ${limit} prompts for today on the ${Auth.tierInfo.label} plan. Upgrade for more!`
      : `Try 1 prompt free — then create an account to keep writing.`;
    if (errorUpgradeLink()) errorUpgradeLink().style.display = 'inline-flex';
    return;
  }

  const customVal  = customGenreGroup()?.style.display !== 'none'
    ? (document.getElementById('custom-genre')?.value?.trim() || '')
    : '';
  const genreLabel = customVal || GENRE_LABELS[genre] || genre;

  const btn = generateBtn();
  const lbl = generateBtnLabel();
  if (btn) btn.disabled = true;
  if (lbl) lbl.textContent = 'Generating…';
  showResult('loading');

  try {
    const prompt = await callGenerateAPI(genreLabel);
    currentPrompt = { genre: genreLabel, prompt, ts: Date.now() };

    if (outputPrompt())    outputPrompt().textContent    = prompt;
    if (outputGenrePill()) outputGenrePill().textContent = genreLabel;
    if (outputMeta())      outputMeta().textContent      = 'Generated ' + new Date().toLocaleTimeString();
    showResult('output');
    Auth.recordUsage();
    updateAppState();

  } catch (err) {
    showResult('error');
    if (errorMsg())        errorMsg().textContent        = String(err).replace('Error: ', '');
    if (errorUpgradeLink()) errorUpgradeLink().style.display = 'none';
  } finally {
    if (btn) btn.disabled = false;
    if (lbl) lbl.textContent = 'Generate Prompt';
  }
}

// ── API call ──────────────────────────────────────────────
// 🔌 BACKEND: Replace this entire function with a fetch() to your server.
// Your server holds the Anthropic API key — NEVER expose it client-side.
//
// Example backend call:
//   const res = await fetch('/api/generate', {
//     method: 'POST',
//     headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${sessionToken}` },
//     body: JSON.stringify({ genre: genreLabel, tier: Auth.tier })
//   });
//   const { prompt } = await res.json();
//   return prompt;

async function callGenerateAPI(genreLabel) {
  await new Promise(r => setTimeout(r, 1100 + Math.random() * 400)); // simulate latency

  // Check for exact or partial match
  const key = Object.keys(DEMO_PROMPTS).find(k =>
    k.toLowerCase() === genreLabel.toLowerCase() ||
    genreLabel.toLowerCase().includes(k.toLowerCase())
  );
  if (key) return DEMO_PROMPTS[key];

  // Fallback for custom genres
  return `A ${genreLabel} story unfolds when an ordinary person makes an extraordinary choice in the most mundane moment of their life — and discovers the world was never as ordinary as they believed.`;
}

// ── Show/hide result states ────────────────────────────────
function showResult(state) {
  const ra = resultArea();
  if (resultIdle())    resultIdle().hidden    = state !== 'idle';
  if (resultLoading()) resultLoading().hidden = state !== 'loading';
  if (resultOutput())  resultOutput().hidden  = state !== 'output';
  if (resultError())   resultError().hidden   = state !== 'error';
  if (ra) ra.classList.toggle('has-output', state === 'output');
}

// ── Copy ──────────────────────────────────────────────────
function copyPrompt() {
  if (!currentPrompt?.prompt) return;
  navigator.clipboard.writeText(currentPrompt.prompt).then(() => {
    const btn = document.getElementById('copy-btn');
    if (btn) { btn.textContent = '✓ Copied!'; setTimeout(() => { btn.textContent = '📋 Copy'; }, 2000); }
  });
}

// ── Save to history (Writer+) ─────────────────────────────
function savePrompt() {
  if (!Auth.hasFeature('history')) {
    openModal('register');
    return;
  }
  if (!currentPrompt) return;
  promptHistory.unshift(currentPrompt);
  if (promptHistory.length > 50) promptHistory.pop();
  localStorage.setItem('fi_history', JSON.stringify(promptHistory));
  renderHistory();
  const btn = document.getElementById('save-btn');
  if (btn) { btn.textContent = '✓ Saved!'; setTimeout(() => { btn.textContent = '🔖 Save'; }, 2000); }
}

function renderHistory() {
  const el = historyListEl();
  if (!el) return;
  el.innerHTML = '';
  if (!promptHistory.length) {
    el.innerHTML = '<p style="font-size:.8rem;color:rgba(255,255,255,.4);font-style:italic;padding:.2rem 0">No saved prompts yet.</p>';
    return;
  }
  promptHistory.forEach(item => {
    const div = document.createElement('div');
    div.className = 'history-item';
    div.innerHTML = `<div class="history-genre">${escHtml(item.genre)}</div><div class="history-snippet">${escHtml(item.prompt)}</div>`;
    div.addEventListener('click', () => {
      currentPrompt = item;
      if (outputPrompt())    outputPrompt().textContent    = item.prompt;
      if (outputGenrePill()) outputGenrePill().textContent = item.genre;
      if (outputMeta())      outputMeta().textContent      = 'Saved · ' + new Date(item.ts).toLocaleDateString();
      showResult('output');
    });
    el.appendChild(div);
  });
}

function clearHistory() {
  if (!confirm('Clear all saved prompts? This cannot be undone.')) return;
  promptHistory = [];
  localStorage.removeItem('fi_history');
  renderHistory();
}

function exportHistory(format) {
  if (!promptHistory.length) { alert('No history to export.'); return; }
  if (!Auth.hasFeature('export')) { openModal('register'); return; }
  if (format === 'csv') {
    downloadCSV([['Genre','Prompt','Date']].concat(promptHistory.map(h => [h.genre, h.prompt, new Date(h.ts).toLocaleDateString()])), 'fi-prompt-history.csv');
  } else {
    downloadText(promptHistory.map(h => `[${h.genre}]\n${h.prompt}`).join('\n\n---\n\n'), 'fi-prompt-history.txt');
  }
}

// ── Weekly generator ──────────────────────────────────────
async function generateWeekly() {
  const btn = document.getElementById('weekly-btn');
  if (btn) { btn.disabled = true; btn.textContent = '⏳ Generating…'; }

  const genres   = Object.keys(GENRE_LABELS).sort(() => Math.random() - .5).slice(0, 3);
  weeklyPrompts  = [];

  const wc = weeklyCard();
  const wb = weeklyTbody();
  if (wc) wc.style.display = 'block';
  if (wb) wb.innerHTML = '<tr><td colspan="2" style="padding:1.5rem;text-align:center;color:var(--muted);font-style:italic">Generating prompts…</td></tr>';

  try {
    for (const key of genres) {
      const label  = GENRE_LABELS[key];
      const prompt = await callGenerateAPI(label);
      weeklyPrompts.push({ genre: label, prompt });
    }
    renderWeeklyTable();
  } catch (err) {
    if (wb) wb.innerHTML = `<tr><td colspan="2" style="padding:1.5rem;color:var(--error)">Error: ${escHtml(String(err))}</td></tr>`;
  } finally {
    if (btn) { btn.disabled = false; btn.innerHTML = '⚡ Generate 3 Prompts'; }
  }
}

function renderWeeklyTable() {
  const tb = weeklyTbody();
  if (!tb) return;
  tb.innerHTML = '';
  weeklyPrompts.forEach(r => {
    const tr = document.createElement('tr');
    tr.innerHTML = `<td><span class="weekly-genre-tag">${escHtml(r.genre)}</span></td><td>${escHtml(r.prompt)}</td>`;
    tb.appendChild(tr);
  });
}

function closeWeekly() {
  const wc = weeklyCard();
  if (wc) wc.style.display = 'none';
  weeklyPrompts = [];
}

function exportWeekly(format) {
  if (!weeklyPrompts.length) return;
  if (format === 'csv') {
    downloadCSV([['Genre','Prompt']].concat(weeklyPrompts.map(r => [r.genre, r.prompt])), 'fi-weekly-prompts.csv');
  } else {
    downloadText(weeklyPrompts.map(r => `[${r.genre}]\n${r.prompt}`).join('\n\n---\n\n'), 'fi-weekly-prompts.txt');
  }
}

// ── Download helpers ──────────────────────────────────────
function downloadCSV(rows, name) {
  const csv = rows.map(r => r.map(c => '"' + String(c).replace(/"/g, '""') + '"').join(',')).join('\r\n');
  _dl(new Blob([csv], { type: 'text/csv' }), name);
}
function downloadText(txt, name) { _dl(new Blob([txt], { type: 'text/plain' }), name); }
function _dl(blob, name) {
  const u = URL.createObjectURL(blob), a = document.createElement('a');
  a.href = u; a.download = name;
  document.body.appendChild(a); a.click();
  document.body.removeChild(a);
  setTimeout(() => URL.revokeObjectURL(u), 1000);
}

function escHtml(s) {
  return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
}

// ── OVERRIDE callGenerateAPI with real backend call ───────
// This replaces the demo function defined earlier in this file
// when the PHP backend is connected.
// To activate: set BACKEND_LIVE = true
const BACKEND_LIVE = false; // ← Set to true when your PHP backend is running

if (BACKEND_LIVE) {
  window.callGenerateAPI = async function(genreLabel) {
    const session = Auth.user;
    const data = await fetch('/api/generate/', {
      method: 'POST',
      credentials: 'include',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        genre:        genreLabel,
        custom_genre: Auth.hasFeature('customGenre') ? genreLabel : '',
      }),
    }).then(r => r.json());

    if (!data.success) throw new Error(data.error || 'Failed to generate prompt.');

    // Update prompts left from server response
    if (Auth._usage && data.prompts_left !== undefined) {
      Auth._usage.prompts_left = data.prompts_left;
      updateAppState();
    }
    return data.prompt;
  };
}
