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

/* ─────────────────────────── helpers ────────────────────────────────── */
function daysAgo(d, h = 0, m = 0) {
  const dt = new Date();
  dt.setDate(dt.getDate() - d);
  dt.setHours(dt.getHours() - h, dt.getMinutes() - m, 0, 0);
  return dt.toISOString().replace('T', ' ').slice(0, 19);
}
function pick(arr) { return arr[Math.floor(Math.random() * arr.length)]; }
function shuffle(arr) {
  const a = [...arr];
  for (let i = a.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [a[i], a[j]] = [a[j], a[i]];
  }
  return a;
}
function rand(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }

/* ─────────────────────────── data ───────────────────────────────────── */
const PASS = bcrypt.hashSync('pass1234', 10);

const TEACHER = { name: 'Наталья Смирнова', email: 'teacher@school.by', role: 'teacher' };

const STUDENTS = [
  { name: 'Алексей Петров',      email: 'petrov@school.by',      skill: 0.85 },
  { name: 'Мария Иванова',       email: 'ivanova@school.by',     skill: 0.78 },
  { name: 'Дмитрий Соколов',     email: 'sokolov@school.by',     skill: 0.62 },
  { name: 'Анна Козлова',        email: 'kozlova@school.by',     skill: 0.91 },
  { name: 'Иван Новиков',        email: 'novikov@school.by',     skill: 0.55 },
  { name: 'Екатерина Морозова',  email: 'morozova@school.by',    skill: 0.73 },
  { name: 'Сергей Волков',       email: 'volkov@school.by',      skill: 0.40 },
  { name: 'Ольга Лебедева',      email: 'lebedeva@school.by',    skill: 0.82 },
  { name: 'Никита Зайцев',       email: 'zajcev@school.by',      skill: 0.48 },
  { name: 'Виктория Семёнова',   email: 'semenova@school.by',    skill: 0.69 },
  { name: 'Артём Павлов',        email: 'pavlov@school.by',      skill: 0.30, lazy: true },
  { name: 'Елена Фёдорова',      email: 'fedorova@school.by',    skill: 0.95 },
  { name: 'Максим Орлов',        email: 'orlov@school.by',       skill: 0.58 },
  { name: 'Юлия Попова',         email: 'popova@school.by',      skill: 0.76, lazy: true },
];

/* ─────────────────────────── insert users ───────────────────────────── */
const insertUser = db.prepare(
  'INSERT OR IGNORE INTO users (email, password_hash, name, role) VALUES (?, ?, ?, ?)'
);
const getUser = db.prepare('SELECT id FROM users WHERE email = ?');

insertUser.run(TEACHER.email, PASS, TEACHER.name, TEACHER.role);
const teacherId = getUser.get(TEACHER.email).id;
console.log(`✓ Teacher: ${TEACHER.name} (id=${teacherId})`);

const studentIds = [];
for (const s of STUDENTS) {
  insertUser.run(s.email, PASS, s.name, 'student');
  const id = getUser.get(s.email).id;
  studentIds.push({ id, skill: s.skill, lazy: !!s.lazy, name: s.name });
}
console.log(`✓ ${STUDENTS.length} students inserted`);

/* ─────────────────────────── classes ────────────────────────────────── */
function genCode() {
  return Math.random().toString(36).slice(2, 9).toUpperCase();
}
const insertClass = db.prepare(
  'INSERT OR IGNORE INTO classes (name, description, teacher_id, invite_code) VALUES (?, ?, ?, ?)'
);
const getClassByName = db.prepare('SELECT id FROM classes WHERE name = ? AND teacher_id = ?');

const classData = [
  { name: '11А · Биология',    desc: 'Подготовка к ЦТ 2026 по биологии',    subject: 'bio',  subjectId: 1 },
  { name: '10Б · Математика',  desc: 'Алгебра и начала анализа',             subject: 'math', subjectId: 3 },
];
const classes = [];
for (const c of classData) {
  insertClass.run(c.name, c.desc, teacherId, genCode());
  const row = getClassByName.get(c.name, teacherId);
  classes.push({ ...c, id: row.id });
  console.log(`✓ Class: "${c.name}" (id=${row.id})`);
}

/* ─────────────────────────── enroll students ────────────────────────── */
const insertMember = db.prepare(
  'INSERT OR IGNORE INTO class_members (class_id, user_id, joined_at) VALUES (?, ?, ?)'
);
// Класс 1 (bio) — все студенты
for (const s of studentIds) {
  insertMember.run(classes[0].id, s.id, daysAgo(rand(20, 40)));
}
// Класс 2 (math) — первые 10 студентов
for (const s of studentIds.slice(0, 10)) {
  insertMember.run(classes[1].id, s.id, daysAgo(rand(15, 35)));
}
console.log('✓ Students enrolled in classes');

/* ─────────────────────────── load questions ─────────────────────────── */
const allQuestions = db.prepare(
  'SELECT id, subject_id, type FROM questions WHERE type = ? OR type IS NULL'
).all('single');

const questionsBySubject = {};
for (const q of allQuestions) {
  if (!questionsBySubject[q.subject_id]) questionsBySubject[q.subject_id] = [];
  questionsBySubject[q.subject_id].push(q);
}

// Load all options grouped by question
const allOptions = db.prepare('SELECT id, question_id, is_correct FROM options').all();
const optionsByQuestion = {};
for (const o of allOptions) {
  if (!optionsByQuestion[o.question_id]) optionsByQuestion[o.question_id] = [];
  optionsByQuestion[o.question_id].push(o);
}

/* ─────────────────────────── simulate session ────────────────────────── */
const insertSession   = db.prepare(
  "INSERT INTO test_sessions (user_id, subject_id, mode, total, score, status, started_at, finished_at) VALUES (?, ?, ?, ?, ?, 'completed', ?, ?)"
);
const insertSQ        = db.prepare(
  'INSERT OR IGNORE INTO session_questions (session_id, question_id, order_index) VALUES (?, ?, ?)'
);
const insertAnswer    = db.prepare(
  'INSERT OR IGNORE INTO user_answers (session_id, question_id, chosen_option_id, is_correct, time_spent_sec, answered_at) VALUES (?, ?, ?, ?, ?, ?)'
);
const insertAssignSes = db.prepare(
  'INSERT OR IGNORE INTO assignment_sessions (assignment_id, user_id, session_id) VALUES (?, ?, ?)'
);

function simulateSession(userId, subjectId, mode, count, skill, daysAgoN) {
  const pool = shuffle(questionsBySubject[subjectId] || []).slice(0, count);
  if (!pool.length) return null;
  const startedAt  = daysAgo(daysAgoN, rand(0, 6));
  const finishedAt = daysAgo(daysAgoN, rand(0, 5), rand(5, 40));

  let score = 0;
  const info = insertSession.run(userId, subjectId, mode, pool.length, 0, startedAt, finishedAt);
  const sessionId = info.lastInsertRowid;

  pool.forEach((q, idx) => {
    insertSQ.run(sessionId, q.id, idx);
    const opts = optionsByQuestion[q.id] || [];
    if (!opts.length) return;
    const correct = opts.find(o => o.is_correct);
    const wrong   = opts.filter(o => !o.is_correct);
    // skill = probability of answering correctly
    const isCorrect = Math.random() < skill;
    let chosen;
    if (isCorrect && correct) {
      chosen = correct;
    } else {
      chosen = wrong.length ? pick(wrong) : pick(opts);
    }
    const wasCorrect = chosen.is_correct ? 1 : 0;
    if (wasCorrect) score++;
    insertAnswer.run(sessionId, q.id, chosen.id, wasCorrect, rand(8, 95), finishedAt);
  });

  // Update score
  db.prepare('UPDATE test_sessions SET score = ? WHERE id = ?').run(score, sessionId);
  return sessionId;
}

/* ─────────────────────────── assignments ────────────────────────────── */
const insertAssign = db.prepare(`
  INSERT OR IGNORE INTO assignments (class_id, title, subject_slug, mode, count, deadline, created_by, created_at)
  VALUES (?, ?, ?, 'exam', ?, ?, ?, ?)
`);
const getAssign = db.prepare('SELECT id FROM assignments WHERE class_id = ? AND title = ?');

const assignmentDefs = [
  // Bio class
  {
    classIdx: 0, title: 'Клетка и её строение',   subjectId: 1, count: 15,
    createdAgo: 28, deadlineAgo: 21, studentSkipChance: 0.0
  },
  {
    classIdx: 0, title: 'Генетика — базовый уровень', subjectId: 1, count: 20,
    createdAgo: 18, deadlineAgo: 11, studentSkipChance: 0.05
  },
  {
    classIdx: 0, title: 'Контрольная: Митоз и мейоз', subjectId: 1, count: 25,
    createdAgo: 10, deadlineAgo: 5, studentSkipChance: 0.10
  },
  {
    classIdx: 0, title: 'Фотосинтез и дыхание', subjectId: 1, count: 15,
    createdAgo: 3, deadlineAgo: null, studentSkipChance: 0.20
  },
  // Math class
  {
    classIdx: 1, title: 'Квадратные уравнения',    subjectId: 3, count: 10,
    createdAgo: 22, deadlineAgo: 16, studentSkipChance: 0.0
  },
  {
    classIdx: 1, title: 'Тригонометрия — тест',    subjectId: 3, count: 15,
    createdAgo: 12, deadlineAgo: 7,  studentSkipChance: 0.08
  },
  {
    classIdx: 1, title: 'Логарифмы и степени',     subjectId: 3, count: 15,
    createdAgo: 4,  deadlineAgo: null, studentSkipChance: 0.25
  },
];

for (const a of assignmentDefs) {
  const cls = classes[a.classIdx];
  const deadline = a.deadlineAgo ? daysAgo(a.deadlineAgo) : null;
  insertAssign.run(cls.id, a.title, cls.subject, a.count, deadline, teacherId, daysAgo(a.createdAgo));
  const row = getAssign.get(cls.id, a.title);
  if (!row) { console.warn(`  ! Could not get assignment id for "${a.title}"`); continue; }
  const assignId = row.id;

  // Determine enrolled students for this class
  const enrolled = a.classIdx === 0 ? studentIds : studentIds.slice(0, 10);

  let done = 0;
  for (const s of enrolled) {
    // Lazy students skip recent assignments
    if (s.lazy && a.studentSkipChance > 0.15) continue;
    // Random skip by skip chance
    if (Math.random() < a.studentSkipChance) continue;

    const sessionId = simulateSession(
      s.id, a.subjectId, 'exam', a.count, s.skill,
      rand(a.deadlineAgo ? a.deadlineAgo : 1, a.createdAgo)
    );
    if (sessionId) {
      insertAssignSes.run(assignId, s.id, sessionId);
      done++;
    }
  }
  console.log(`✓ Assignment "${a.title}" — ${done}/${enrolled.length} completed`);
}

/* ─────────────────────────── free-form sessions ─────────────────────── */
// Some students did extra practice on their own
const practiceSubjects = [[1, 'bio'], [3, 'math']];
for (const s of studentIds) {
  if (s.lazy) continue;
  const extraCount = rand(1, 4);
  for (let i = 0; i < extraCount; i++) {
    const [subId] = pick(practiceSubjects);
    simulateSession(s.id, subId, 'practice', rand(10, 25), s.skill + 0.05, rand(1, 30));
  }
}
console.log('✓ Extra practice sessions simulated');

/* ─────────────────────────── announcements ──────────────────────────── */
const insertAnn = db.prepare(
  'INSERT INTO announcements (class_id, author_id, text, created_at) VALUES (?, ?, ?, ?)'
);
const annTexts = [
  [0, '📅 Напоминаю: контрольная по митозу пройдёт в следующую пятницу. Повторите темы деления клетки.', 9],
  [0, '✅ Результаты по теме «Клетка» проверены. Молодцы! Средний балл — 74%. Слабее всего — органоиды.', 20],
  [0, '📚 Для подготовки к ЦТ рекомендую дополнительно пройти тест по фотосинтезу в системе.', 5],
  [1, '🧮 Разбор ошибок по квадратным уравнениям будет в среду, 14:00, кабинет 204.', 11],
  [1, '⚠️ Дедлайн по логарифмам — в пятницу. Кто не сдал тригонометрию — сдайте до конца недели.', 3],
];
for (const [classIdx, text, ago] of annTexts) {
  insertAnn.run(classes[classIdx].id, teacherId, text, daysAgo(ago));
}
console.log('✓ Announcements created');

/* ─────────────────────────── notifications ──────────────────────────── */
const insertNotif = db.prepare(
  'INSERT INTO notifications (user_id, type, message, link, is_read, created_at) VALUES (?, ?, ?, ?, ?, ?)'
);
// Teacher gets notifs about students completing assignments
for (const s of studentIds.slice(0, 6)) {
  insertNotif.run(teacherId, 'session',
    `«${s.name}» сдал «Генетика — базовый уровень» — ${rand(55, 95)}%`,
    '/classes.html', 1, daysAgo(rand(5, 15)));
}
// Students get assignment notifs
for (const s of studentIds) {
  insertNotif.run(s.id, 'assignment', '📋 Для вас задание: «Контрольная: Митоз и мейоз»', '/dashboard.html', 1, daysAgo(10));
  insertNotif.run(s.id, 'assignment', '📋 Для вас задание: «Фотосинтез и дыхание»', '/dashboard.html', rand(0,1), daysAgo(3));
}
console.log('✓ Notifications created');

/* ─────────────────────────── summary ────────────────────────────────── */
const stats = {
  users:    db.prepare('SELECT COUNT(*) as n FROM users').get().n,
  sessions: db.prepare('SELECT COUNT(*) as n FROM test_sessions').get().n,
  answers:  db.prepare('SELECT COUNT(*) as n FROM user_answers').get().n,
  assigns:  db.prepare('SELECT COUNT(*) as n FROM assignments').get().n,
};
console.log('\n═══ Seed complete ═══');
console.log(`  Users:        ${stats.users}`);
console.log(`  Sessions:     ${stats.sessions}`);
console.log(`  Answers:      ${stats.answers}`);
console.log(`  Assignments:  ${stats.assigns}`);
console.log('\n  Password for all accounts: pass1234');
console.log(`  Teacher:  ${TEACHER.email}`);
console.log(`  Students: ${STUDENTS[0].email} … ${STUDENTS[STUDENTS.length-1].email}`);
