'use strict';
const db = require('../../db/db');

/* ═══════════════════════════════════════════════════════════════════════
   Gamification — shared module: helpers + stmts + defs
   All sibling files (./service, ./api, ./admin) import from here.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── XP thresholds: level = floor(sqrt(xp / 100)) + 1 ── */
function xpToLevel(xp)   { return Math.floor(Math.sqrt((xp || 0) / 100)) + 1; }
function levelMinXp(lv)  { return (lv - 1) * (lv - 1) * 100; }
function levelMaxXp(lv)  { return lv * lv * 100; }

const RANKS = [
  [1,  'Новичок'],
  [5,  'Ученик'],
  [10, 'Знаток'],
  [15, 'Эксперт'],
  [20, 'Мастер'],
  [30, 'Гуру'],
];
function rankName(level) {
  let name = 'Новичок';
  for (const [min, r] of RANKS) if (level >= min) name = r;
  return name;
}

/* ── Daily-goal tiers (used by daily logic + setGoalTier API) ── */
const GOAL_TIERS = {
  easy:   { tests: 2, xp: 100, bonus: 30,  label: 'Лёгкая' },
  medium: { tests: 3, xp: 200, bonus: 50,  label: 'Средняя' },
  hard:   { tests: 5, xp: 500, bonus: 100, label: 'Тяжёлая' },
};

/* ── Achievement definitions (seed via seedAchievements()) ── */
const ACHIEVEMENT_DEFS = [
  // First steps
  { slug: 'first_test',     title: 'Первый тест',         icon: 'target',     cat: 'start',   desc: 'Пройти свой первый тест' },
  { slug: 'first_perfect',  title: 'Идеальный результат', icon: 'hundred',    cat: 'start',   desc: 'Получить 100% на тесте' },
  { slug: 'first_class',    title: 'Вступил в класс',     icon: 'school',     cat: 'start',   desc: 'Присоединиться к классу' },
  // Streaks
  { slug: 'streak_3',       title: 'Три дня подряд',      icon: 'flame',      cat: 'streak',  desc: '3 дня активности подряд' },
  { slug: 'streak_7',       title: 'Неделя подряд',       icon: 'flame',      cat: 'streak',  desc: '7 дней активности подряд' },
  { slug: 'streak_30',      title: 'Месяц подряд',        icon: 'flame',      cat: 'streak',  desc: '30 дней активности подряд' },
  // Volume
  { slug: 'tests_10',       title: '10 тестов',            icon: 'file-text', cat: 'volume',  desc: 'Завершить 10 тестов' },
  { slug: 'tests_50',       title: '50 тестов',            icon: 'books',     cat: 'volume',  desc: 'Завершить 50 тестов' },
  { slug: 'tests_100',      title: '100 тестов',           icon: 'trophy',    cat: 'volume',  desc: 'Завершить 100 тестов' },
  // Mastery
  { slug: 'score_90',       title: 'Отличник',             icon: 'star',      cat: 'mastery', desc: '5 тестов подряд на 90%+' },
  { slug: 'speed_demon',    title: 'Скорострел',           icon: 'zap',       cat: 'mastery', desc: 'Тест на 90%+ за <50% времени' },
  // Levels
  { slug: 'level_5',        title: 'Ученик',               icon: 'book-open', cat: 'level',   desc: 'Достичь 5 уровня' },
  { slug: 'level_10',       title: 'Знаток',               icon: 'brain',     cat: 'level',   desc: 'Достичь 10 уровня' },
  { slug: 'level_20',       title: 'Мастер',               icon: 'crown',     cat: 'level',   desc: 'Достичь 20 уровня' },
  { slug: 'level_3',        title: 'Начинающий',           icon: 'book-open', cat: 'level',   desc: 'Достичь 3 уровня' },
  // XP milestones
  { slug: 'xp_1000',        title: '1000 XP',              icon: 'diamond',   cat: 'xp',      desc: 'Набрать 1000 XP' },
  { slug: 'xp_5000',        title: '5000 XP',              icon: 'diamond',   cat: 'xp',      desc: 'Набрать 5000 XP' },
  { slug: 'xp_10000',       title: '10 000 XP',            icon: 'diamond',   cat: 'xp',      desc: 'Набрать 10 000 XP' },
  // Lab / experiments
  { slug: 'lab_first',       title: 'Первый опыт',         icon: 'flask-conical', cat: 'lab', desc: 'Провести первый эксперимент в лаборатории' },
  { slug: 'lab_5',           title: 'Юный химик',          icon: 'flask-conical', cat: 'lab', desc: 'Провести 5 экспериментов' },
  { slug: 'lab_20',          title: 'Лаборант',            icon: 'test-tubes',    cat: 'lab', desc: 'Провести 20 экспериментов' },
  { slug: 'lab_50',          title: 'Исследователь',       icon: 'microscope',    cat: 'lab', desc: 'Провести 50 экспериментов' },
  { slug: 'lab_reactions_10',title: '10 реакций',          icon: 'atom',          cat: 'lab', desc: 'Обнаружить 10 различных реакций' },
  { slug: 'lab_reactions_30',title: '30 реакций',          icon: 'atom',          cat: 'lab', desc: 'Обнаружить 30 различных реакций' },
  // Red Book
  { slug: 'rb_first',        title: 'Первый вид КК',        icon: 'leaf',          cat: 'redbook', desc: 'Открыть первый вид Красной книги' },
  { slug: 'rb_10',           title: '10 видов КК',          icon: 'leaf',          cat: 'redbook', desc: 'Открыть 10 видов Красной книги' },
  { slug: 'rb_25',           title: 'Четверть коллекции',   icon: 'trees',         cat: 'redbook', desc: 'Открыть 25 видов Красной книги' },
  { slug: 'rb_50',           title: 'Половина коллекции',   icon: 'trees',         cat: 'redbook', desc: 'Открыть 50 видов Красной книги' },
  { slug: 'rb_all_cr',       title: 'Защитник природы',     icon: 'shield-check',  cat: 'redbook', desc: 'Открыть все CR-виды Красной книги' },
  { slug: 'rb_quest_first',  title: 'Первый квест КК',      icon: 'map',           cat: 'redbook', desc: 'Выполнить первый квест Красной книги' },
  { slug: 'rb_quest_5',      title: 'Квестмастер КК',       icon: 'map-pin',       cat: 'redbook', desc: 'Выполнить 5 квестов Красной книги' },
  { slug: 'rb_sighting',     title: 'Наблюдатель',          icon: 'eye',           cat: 'redbook', desc: 'Добавить первое наблюдение вида' },
  // Theory / Library
  { slug: 'theory_first',    title: 'Первый урок',          icon: 'book-open',     cat: 'theory',  desc: 'Прочитать первый урок' },
  { slug: 'theory_10',       title: 'Читатель',             icon: 'library',       cat: 'theory',  desc: 'Прочитать 10 уроков' },
  { slug: 'theory_course',   title: 'Завершил курс',        icon: 'graduation-cap',cat: 'theory',  desc: 'Пройти полный курс целиком' },
  // Assignments
  { slug: 'assign_first',    title: 'Первое задание',       icon: 'clipboard',       cat: 'assign', desc: 'Сдать первое задание' },
  { slug: 'assign_10',       title: '10 заданий',           icon: 'clipboard-check', cat: 'assign', desc: 'Сдать 10 заданий' },
];

/* ── Avatar frames (unlocked by achievement slug) ── */
const AVATAR_FRAMES = [
  { id: 'default',     name: 'Стандарт',   css: '',                                                                                       unlock: null },
  { id: 'fire',        name: 'Огненная',   css: 'box-shadow:0 0 0 3px #FF6B35,0 0 12px rgba(255,107,53,0.4)',                              unlock: 'streak_7' },
  { id: 'diamond',     name: 'Бриллиант',  css: 'box-shadow:0 0 0 3px #06D6E0,0 0 12px rgba(6,214,224,0.4)',                              unlock: 'xp_5000' },
  { id: 'gold',        name: 'Золотая',    css: 'box-shadow:0 0 0 3px #FFD700,0 0 12px rgba(255,215,0,0.4)',                              unlock: 'tests_100' },
  { id: 'violet_glow', name: 'Фиолет',     css: 'box-shadow:0 0 0 3px #9B5DE5,0 0 16px rgba(155,93,229,0.5)',                              unlock: 'level_10' },
  { id: 'rainbow',     name: 'Радуга',     css: 'background:conic-gradient(#FF6B6B,#FFD93D,#6BCB77,#4D96FF,#9B5DE5,#FF6B6B);padding:3px', unlock: 'level_20' },
  { id: 'crown',       name: 'Корона',     css: 'box-shadow:0 0 0 3px #FFD700,0 0 20px rgba(255,215,0,0.6)',                              unlock: 'xp_10000' },
  { id: 'perfect',     name: 'Идеал',      css: 'box-shadow:0 0 0 3px #06D664,0 0 12px rgba(6,214,100,0.4)',                              unlock: 'first_perfect' },
];

/* ── Prepared statements (module-level to avoid re-parsing per request) ── */
const stmts = {
  // XP & coins
  insertXpLog:       db.prepare('INSERT INTO xp_log (user_id, amount, reason) VALUES (?, ?, ?)'),
  incrXP:            db.prepare('UPDATE users SET xp = xp + ? WHERE id = ?'),
  getXP:             db.prepare('SELECT xp FROM users WHERE id = ?'),
  setLevel:          db.prepare('UPDATE users SET level = ? WHERE id = ?'),
  incrCoins:         db.prepare('UPDATE users SET coins = coins + ? WHERE id = ?'),

  // Streak
  getStreak:         db.prepare('SELECT streak_current, streak_best, streak_date FROM users WHERE id = ?'),
  setStreak:         db.prepare('UPDATE users SET streak_current = ?, streak_best = ?, streak_date = ? WHERE id = ?'),

  // getXPInfo
  getUserXPInfo:     db.prepare('SELECT xp, level, streak_current, streak_best, streak_date FROM users WHERE id = ?'),

  countUserAssignments: db.prepare(`SELECT COUNT(*) as n FROM assignment_sessions ass JOIN test_sessions ts ON ts.id = ass.session_id WHERE ts.user_id = ? AND ts.status = 'completed'`),

  // Achievements
  getAchBySlug:      db.prepare('SELECT id, title, icon FROM achievements WHERE slug = ?'),
  hasUserAch:        db.prepare('SELECT 1 FROM user_achievements WHERE user_id = ? AND achievement_id = ?'),
  insertUserAch:     db.prepare('INSERT INTO user_achievements (user_id, achievement_id) VALUES (?, ?)'),
  insertAchNotif:    db.prepare("INSERT INTO notifications (user_id, type, message, link) VALUES (?, 'achievement', ?, '/profile')"),
  getUserForAch:     db.prepare(`
    SELECT u.xp, u.level, u.streak_current, u.lab_experiments, u.lab_reactions,
           (SELECT COUNT(*) FROM test_sessions WHERE user_id = u.id AND status = 'completed')                   AS test_count,
           (SELECT COUNT(*) FROM test_sessions WHERE user_id = u.id AND status = 'completed' AND score = total) AS perfect_count,
           (SELECT COUNT(*) FROM class_members  WHERE user_id = u.id)                                           AS class_count
    FROM users u WHERE u.id = ?
  `),
  getLast5Tests:     db.prepare(`
    SELECT score, total FROM test_sessions
    WHERE user_id = ? AND status = 'completed'
    ORDER BY finished_at DESC LIMIT 5
  `),

  // Lab
  incrLabExp:        db.prepare('UPDATE users SET lab_experiments = lab_experiments + 1 WHERE id = ?'),
  incrLabReact:      db.prepare('UPDATE users SET lab_reactions = lab_reactions + ? WHERE id = ?'),

  // Daily goals
  getDailyGoal:      db.prepare('SELECT * FROM daily_goals WHERE user_id = ? AND date = ?'),
  getUserGoalTier:   db.prepare('SELECT goal_tier FROM users WHERE id = ?'),
  insertDailyGoal:   db.prepare('INSERT INTO daily_goals (user_id, date, tests_target, tests_done, xp_target, xp_earned) VALUES (?, ?, ?, 0, ?, 0)'),
  incrDailyGoal:     db.prepare('UPDATE daily_goals SET tests_done = tests_done + ?, xp_earned = xp_earned + ? WHERE user_id = ? AND date = ?'),
  checkGoalBonus:    db.prepare("SELECT 1 FROM xp_log WHERE user_id = ? AND reason = 'daily_goal' AND date(created_at) = ?"),

  // Challenges
  getOpenChallenges: db.prepare('SELECT * FROM challenges WHERE user_id = ? AND week = ? AND completed = 0'),
  incrChallenge:     db.prepare('UPDATE challenges SET progress = MIN(progress + ?, target) WHERE id = ?'),
  getChallengeById:  db.prepare('SELECT * FROM challenges WHERE id = ?'),
  completeChallenge: db.prepare('UPDATE challenges SET completed = 1 WHERE id = ?'),
  getChallengesWeek: db.prepare('SELECT * FROM challenges WHERE user_id = ? AND week = ? ORDER BY completed, id'),
  getChallengeOwned: db.prepare('SELECT * FROM challenges WHERE id = ? AND user_id = ?'),
  markClaimed:       db.prepare('UPDATE challenges SET claimed = 1 WHERE id = ?'),

  // API handlers
  getUserPrefs:      db.prepare('SELECT goal_tier, avatar_frame FROM users WHERE id = ?'),
  getUnlockedSlugs:  db.prepare('SELECT a.slug FROM user_achievements ua JOIN achievements a ON a.id = ua.achievement_id WHERE ua.user_id = ?'),
  getUserFrame:      db.prepare('SELECT avatar_frame FROM users WHERE id = ?'),
  checkFrameUnlock:  db.prepare('SELECT a.id FROM achievements a JOIN user_achievements ua ON ua.achievement_id = a.id WHERE a.slug = ? AND ua.user_id = ?'),
  setUserFrame:      db.prepare('UPDATE users SET avatar_frame = ? WHERE id = ?'),
  setUserGoalTier:   db.prepare('UPDATE users SET goal_tier = ? WHERE id = ?'),
  getAllAchs:        db.prepare('SELECT id, slug, title, icon, category, description FROM achievements ORDER BY id'),
  getUserAchs:       db.prepare('SELECT achievement_id, unlocked_at FROM user_achievements WHERE user_id = ?'),
  xpHistory:         db.prepare('SELECT amount, reason, created_at FROM xp_log WHERE user_id = ? ORDER BY created_at DESC LIMIT ?'),

  // Admin
  checkUserById:     db.prepare('SELECT id FROM users WHERE id = ?'),
  getUserGamInfo:    db.prepare('SELECT xp, level, coins FROM users WHERE id = ?'),
  adminResetUser:    db.prepare("UPDATE users SET xp=0, level=1, coins=0, streak_current=0, streak_best=0, streak_date=NULL, avatar_frame='default' WHERE id=?"),
  deleteXpLog:       db.prepare('DELETE FROM xp_log WHERE user_id=?'),
  deleteUserAchs:    db.prepare('DELETE FROM user_achievements WHERE user_id=?'),
  deleteDailyGoals:  db.prepare('DELETE FROM daily_goals WHERE user_id=?'),
  deleteChallenges:  db.prepare('DELETE FROM challenges WHERE user_id=?'),
  deleteUserPurch:   db.prepare('DELETE FROM user_purchases WHERE user_id=?'),
  adminGetUserFull:  db.prepare('SELECT id, name, xp, level, coins, streak_current, streak_best, goal_tier, avatar_frame FROM users WHERE id=?'),
  adminGetUserAchs:  db.prepare('SELECT a.slug, a.title, a.icon, ua.unlocked_at FROM user_achievements ua JOIN achievements a ON a.id=ua.achievement_id WHERE ua.user_id=?'),
  adminGetUserPurch: db.prepare('SELECT si.name, si.type, up.purchased_at FROM user_purchases up JOIN shop_items si ON si.id=up.item_id WHERE up.user_id=?'),
  adminGetUserXPH:   db.prepare('SELECT amount, reason, created_at FROM xp_log WHERE user_id=? ORDER BY created_at DESC LIMIT 30'),
  adminTotalXP:      db.prepare('SELECT COALESCE(SUM(xp),0) as v FROM users'),
  adminTotalCoins:   db.prepare('SELECT COALESCE(SUM(coins),0) as v FROM users'),
  adminAvgLevel:     db.prepare("SELECT ROUND(AVG(level),1) as v FROM users WHERE role='student'"),
  adminAchCount:     db.prepare('SELECT COUNT(*) as v FROM user_achievements'),
  adminTopXP:        db.prepare("SELECT id, name, xp, level, coins FROM users WHERE role='student' ORDER BY xp DESC LIMIT 10"),
  adminRecentXP:     db.prepare('SELECT xl.amount, xl.reason, xl.created_at, u.name FROM xp_log xl JOIN users u ON u.id=xl.user_id ORDER BY xl.created_at DESC LIMIT 20'),
  adminTotalPurch:   db.prepare('SELECT COUNT(*) as v FROM user_purchases'),
  adminRecentPurch:  db.prepare(`SELECT up.purchased_at, u.name AS user_name, si.name AS item_name, si.price, si.type
    FROM user_purchases up JOIN users u ON u.id=up.user_id JOIN shop_items si ON si.id=up.item_id
    ORDER BY up.purchased_at DESC LIMIT 20`),
};

module.exports = {
  xpToLevel, levelMinXp, levelMaxXp, rankName, RANKS,
  GOAL_TIERS, ACHIEVEMENT_DEFS, AVATAR_FRAMES,
  stmts,
};
