'use strict';
// ═══════════════════════════════════════════════
// js/badges.js — Achievement + journey badges
// All badges are computed fresh from data — never stored, always derived.
// Return format: [{ key, emoji, tooltip, large }]
// ═══════════════════════════════════════════════

// ── Weekly streak — consecutive weeks with logged stats ──
function computeWeeklyStreak(weeklyStats) {
  if (!weeklyStats || !weeklyStats.length) return 0;
  const sorted = [...weeklyStats].sort((a, b) => b.date.localeCompare(a.date));
  const now = Date.now();
  const mostRecent = new Date(sorted[0].date + 'T00:00:00').getTime();
  // Streak is only alive if most recent stat is within 9 days of today
  if (now - mostRecent > 9 * 86400000) return 0;
  let streak = 1;
  for (let i = 1; i < sorted.length; i++) {
    const cur  = new Date(sorted[i - 1].date + 'T00:00:00').getTime();
    const prev = new Date(sorted[i].date + 'T00:00:00').getTime();
    if (cur - prev > 9 * 86400000) break; // gap too large — streak ends
    streak++;
  }
  return streak;
}

// ── Daily tracker streak — consecutive days with at least one timer session ──
function computeDailyTrackerStreak(timerSessions) {
  if (!timerSessions || !timerSessions.length) return 0;
  // Build set of unique day strings (YYYY-MM-DD) from startedAt timestamps
  const daySet = new Set(
    timerSessions
      .filter(s => s.startedAt)
      .map(s => new Date(s.startedAt).toISOString().slice(0, 10))
  );
  const days = [...daySet].sort((a, b) => b.localeCompare(a)); // desc
  if (!days.length) return 0;
  const now = Date.now();
  const msToday = new Date(new Date().toISOString().slice(0, 10) + 'T00:00:00').getTime();
  const mostRecentMs = new Date(days[0] + 'T00:00:00').getTime();
  // Streak only alive if most recent session was today or yesterday
  if (msToday - mostRecentMs > 86400000) return 0;
  let streak = 1;
  for (let i = 1; i < days.length; i++) {
    const cur  = new Date(days[i - 1] + 'T00:00:00').getTime();
    const prev = new Date(days[i]     + 'T00:00:00').getTime();
    if (cur - prev > 86400000) break; // gap > 1 day — streak ends
    streak++;
  }
  return streak;
}

// Computes badges from provided data. contacts may be empty [] for buddy views.
// timerSessions is optional — omit for buddy views (private data).
function computeBadgesFrom(entries, profile, contacts, weeklyStats, timerSessions) {
  const badges = [];
  if (!entries || !entries.length) return badges;

  const sortedAsc  = [...entries].sort((a, b) => a.date.localeCompare(b.date));
  const sortedDesc = [...entries].sort((a, b) => b.date.localeCompare(a.date));
  const firstEntry  = sortedAsc[0];
  const latestEntry = sortedDesc[0];

  // ── Journey badge — one evolving badge, shows highest tier earned ──
  const yearsRestoring = (Date.now() - new Date(firstEntry.date + 'T00:00:00').getTime()) / (365.25 * 24 * 3600000);
  if      (yearsRestoring >= 5) badges.push({ key: 'journey', emoji: '🌳', label: '5y', tooltip: '5+ years restoring',  large: false });
  else if (yearsRestoring >= 4) badges.push({ key: 'journey', emoji: '🌿', label: '4y', tooltip: '4 years restoring',   large: false });
  else if (yearsRestoring >= 3) badges.push({ key: 'journey', emoji: '🍀', label: '3y', tooltip: '3 years restoring',   large: false });
  else if (yearsRestoring >= 2) badges.push({ key: 'journey', emoji: '☘️', label: '2y', tooltip: '2 years restoring',   large: false });
  else if (yearsRestoring >= 1) badges.push({ key: 'journey', emoji: '🌱', label: '1y', tooltip: '1 year restoring',    large: false });

  // ── CI Gained — live number ──
  const startCI   = profile?.startingCI ?? firstEntry.ci;
  const currentCI = latestEntry.ci;
  if (startCI != null && currentCI != null && currentCI > startCI) {
    const gained = currentCI - startCI;
    badges.push({ key: 'ci_gained', emoji: '📈', label: `+${gained} CI`, tooltip: `${gained} CI level${gained !== 1 ? 's' : ''} gained since starting`, large: false });
  }

  // ── Fully Restored — largest badge ──
  const isRestored = !!(profile?.fullyRestoredOn ||
    (profile?.goalCI != null && currentCI != null && currentCI >= profile.goalCI));
  if (isRestored) {
    badges.push({ key: 'restored', emoji: '👑', label: 'Restored', tooltip: 'Fully Restored', large: true });
  }

  // ── Multi-Method — more than 2 distinct devices across all entries ──
  const allDevices = new Set();
  entries.forEach(e => {
    (e.tuggingDevices  || []).forEach(d => allDevices.add(d));
    (e.retainingDevices || []).forEach(d => allDevices.add(d));
  });
  if (allDevices.size > 2) {
    badges.push({ key: 'multi_method', emoji: '🔧', label: `${allDevices.size} methods`, tooltip: `${allDevices.size} different methods used`, large: false });
  }

  // ── Buddy-count badges — own user only (contacts list provided) ──
  if (contacts && contacts.length) {
    const active = contacts.filter(c => !c.pendingRemoval && !c.removedAt && !c.forgottenAt);
    if (active.length >= 5) {
      badges.push({ key: 'buddies', emoji: '🌐', label: `${active.length} buddies`, tooltip: '5+ buddies connected', large: false });
    }
    const mutualTrusted = active.filter(c => c.trusted && c.senderTrusts).length;
    if (mutualTrusted >= 3) {
      badges.push({ key: 'trusted', emoji: '💛', label: `${mutualTrusted} trusted`, tooltip: `${mutualTrusted} trusted buddies`, large: false });
    }
  }

  // ── Weekly streak — 🔥 N weeks ──
  const streak = computeWeeklyStreak(weeklyStats || []);
  if (streak >= 2) {
    badges.push({ key: 'weekly_streak', emoji: '🔥', label: `${streak} wk streak`, tooltip: `${streak} week streak`, large: false });
  }

  // ── Photo count — 📷 N (journal only — gallery added by computeBadges for own profile) ──
  const photoCount = entries.reduce((n, e) => n + ((e.imgFront || e.hasImgFront) ? 1 : 0) + ((e.imgLeft || e.hasImgLeft) ? 1 : 0) + ((e.imgRight || e.hasImgRight) ? 1 : 0), 0);
  if (photoCount >= 1) {
    badges.push({ key: 'photos', emoji: '📷', label: `${photoCount} photo${photoCount !== 1 ? 's' : ''}`, tooltip: `${photoCount} photo${photoCount !== 1 ? 's' : ''} uploaded`, large: false });
  }

  // ── Daily tracker streak — ⏱️ N days (own user only — timerSessions not shared) ──
  if (timerSessions && timerSessions.length) {
    const dayStreak = computeDailyTrackerStreak(timerSessions);
    if (dayStreak >= 3) {
      badges.push({ key: 'timer_streak', emoji: '⏱️', label: `${dayStreak}d streak`, tooltip: `${dayStreak} day tracker streak`, large: false });
    }

    // ── Peak Mitosis — 6+ hours of tugging in a single day ──
    const peakDays = countPeakMitosisDays(timerSessions);
    if (peakDays >= 1) {
      badges.push({
        key: 'peak_mitosis', emoji: '🧬',
        label: peakDays > 1 ? `Peak Mitosis ×${peakDays}` : 'Peak Mitosis',
        tooltip: `6+ hours of tugging in one day, peak mitotic activity (${peakDays} day${peakDays !== 1 ? 's' : ''})`,
        large: false
      });
    }
  }

  return badges;
}

// ── Peak Mitosis helpers ──
// Per-day tugging totals; a session counts toward the day it started.
const PEAK_MITOSIS_MS = 6 * 3600000; // 6 hours of daily tension

function _tugTotalForDay(timerSessions, dayStr) {
  return (timerSessions || [])
    .filter(s => s.type === 'tugging' && s.endedAt && s.durationMs > 0 &&
      new Date(s.startedAt).toISOString().slice(0, 10) === dayStr)
    .reduce((ms, s) => ms + s.durationMs, 0);
}

function countPeakMitosisDays(timerSessions) {
  const totals = {};
  (timerSessions || []).forEach(s => {
    if (s.type !== 'tugging' || !s.endedAt || !(s.durationMs > 0)) return;
    const day = new Date(s.startedAt).toISOString().slice(0, 10);
    totals[day] = (totals[day] || 0) + s.durationMs;
  });
  return Object.values(totals).filter(ms => ms >= PEAK_MITOSIS_MS).length;
}

// Called after a tugging session is saved: celebrate crossing 6h for the day,
// at most once per day.
function checkPeakMitosisToast(timerSessions) {
  try {
    const today = new Date().toISOString().slice(0, 10);
    if (localStorage.getItem('frj_mitosis_day') === today) return;
    if (_tugTotalForDay(timerSessions, today) < PEAK_MITOSIS_MS) return;
    localStorage.setItem('frj_mitosis_day', today);
    if (typeof toast === 'function') toast('🧬 Peak Mitosis! 6+ hours of tugging today. Maximum growth signal.');
  } catch (e) { /* non-fatal */ }
}

// Convenience: compute own badges from live app state
function computeBadges() {
  const entries      = typeof getEntries      === 'function' ? getEntries()      : [];
  const profile      = typeof getProfile      === 'function' ? getProfile()      : {};
  const contacts     = typeof getContacts     === 'function' ? getContacts()     : [];
  const weeklyStats  = typeof getWeeklyStats  === 'function' ? getWeeklyStats()  : [];
  const timerSessions = typeof getTimerSessions === 'function' ? getTimerSessions() : [];
  const badges = computeBadgesFrom(entries, profile, contacts, weeklyStats, timerSessions);
  // Add own gallery photos to the photo count (only for own profile — not shared to buddies)
  const galCount = typeof getGalleries === 'function'
    ? getGalleries().reduce((n, g) => n + (g.items?.length || 0), 0) : 0;
  if (galCount > 0) {
    const pi = badges.findIndex(b => b.key === 'photos');
    if (pi >= 0) {
      const total = parseInt(badges[pi].label) + galCount;
      badges[pi].label = `${total} photo${total !== 1 ? 's' : ''}`;
      badges[pi].tooltip = `${total} photo${total !== 1 ? 's' : ''} uploaded`;
    } else {
      badges.push({ key: 'photos', emoji: '📷', label: `${galCount} photo${galCount !== 1 ? 's' : ''}`, tooltip: `${galCount} photo${galCount !== 1 ? 's' : ''} uploaded`, large: false });
    }
  }
  return badges;
}
