import { anthropicApi } from './api';
import * as db from './db';

const QUIZ_SYSTEM = `You are a quiz generator for Respellion, an internal IT company learning platform.
You generate multiple-choice questions to test employee knowledge on specific topics.
Always write in clear, professional English.
ALWAYS return valid JSON only — no markdown code blocks, no extra text.`;

async function selectTestTopics(userId, weekNumber) {
  const topics = await db.getTopics();
  if (!topics || topics.length === 0) return { primaryTopic: null, reviewTopics: [] };

  const str = `${userId}:${weekNumber}`;
  let hash = 0;
  for (let i = 0; i < str.length; i++) {
    hash = (hash << 5) - hash + str.charCodeAt(i);
    hash |= 0;
  }
  const primaryIndex = Math.abs(hash) % topics.length;
  const primaryTopic = topics[primaryIndex];

  const others = topics.filter((_, i) => i !== primaryIndex);
  const shuffled = others.sort(() => 0.5 - Math.random());
  const reviewTopics = shuffled.slice(0, Math.min(5, shuffled.length));

  return { primaryTopic, reviewTopics };
}

export async function getCachedQuiz(userId, weekNumber) {
  return db.getCachedQuiz(userId, weekNumber);
}

export async function forceGenerateTopicQuestions(topic, count = 10) {
  let bank = await db.getQuizBank(topic.id);

  const prompt = `Generate exactly ${count} multiple-choice quiz questions based on this knowledge topic:

Topic: ${topic.label}
Type: ${topic.type}
Description: ${topic.description}

Return ONLY a JSON object with this structure:
{
  "questions": [
    {
      "id": "unique-id-string",
      "question": "The question text",
      "topicLabel": "${topic.label}",
      "options": ["A) First option", "B) Second option", "C) Third option", "D) Fourth option"],
      "correctIndex": 0,
      "explanation": "A clear 1-2 sentence explanation of why the correct answer is correct."
    }
  ]
}

Rules:
- Each question must have exactly 4 options.
- correctIndex is 0-based (0=A, 1=B, 2=C, 3=D).
- Mix difficulty: 4 easy, 4 medium, 2 hard.
- Make questions specific and practical, not trivial.`;

  const responseText = await anthropicApi.generateContent(QUIZ_SYSTEM, prompt);
  let newQuestions = [];
  try {
    const jsonMatch = responseText.match(/\{[\s\S]*\}/);
    const parsed = JSON.parse(jsonMatch ? jsonMatch[0] : responseText);
    newQuestions = parsed.questions || [];
    newQuestions.forEach(q => {
      q.id = `${topic.id}-${Math.random().toString(36).substr(2, 9)}`;
    });
  } catch (e) {
    console.error('Failed to generate questions for topic', topic.label, e);
    throw new Error(`Could not generate questions for ${topic.label}`);
  }

  bank = [...bank, ...newQuestions];
  await db.setQuizBank(topic.id, bank);
  return newQuestions;
}

async function getOrGenerateTopicQuestions(topic, count) {
  let bank = await db.getQuizBank(topic.id);

  if (bank.length < count) {
    await forceGenerateTopicQuestions(topic, 10);
    bank = await db.getQuizBank(topic.id);
  }

  const shuffled = [...bank].sort(() => 0.5 - Math.random());
  return shuffled.slice(0, Math.min(count, shuffled.length));
}

export async function getTopicQuestionBank(topicId) {
  return db.getQuizBank(topicId);
}

export async function deleteQuestion(topicId, questionId) {
  return db.deleteQuestionFromBank(topicId, questionId);
}

export async function generateWeeklyQuiz(userId, weekNumber, force = false) {
  if (!force) {
    const cached = await db.getCachedQuiz(userId, weekNumber);
    if (cached) return cached;
  }

  const { primaryTopic, reviewTopics } = await selectTestTopics(userId, weekNumber);
  if (!primaryTopic) throw new Error('No topics available to generate a quiz.');

  const questions = [];

  const primaryQs = await getOrGenerateTopicQuestions(primaryTopic, 5);
  questions.push(...primaryQs);

  for (const rt of reviewTopics) {
    const rtQs = await getOrGenerateTopicQuestions(rt, 1);
    questions.push(...rtQs);
  }

  if (questions.length < 10) {
    const needed = 10 - questions.length;
    const extraQs = await getOrGenerateTopicQuestions(primaryTopic, needed + 5);
    const existingIds = new Set(questions.map(q => q.id));
    for (const eq of extraQs) {
      if (!existingIds.has(eq.id) && questions.length < 10) {
        questions.push(eq);
      }
    }
  }

  questions.sort(() => 0.5 - Math.random());

  const quiz = {
    questions,
    meta: {
      userId,
      weekNumber,
      generatedAt: new Date().toISOString(),
      primaryTopic: primaryTopic.label,
    },
  };

  await db.setCachedQuiz(userId, weekNumber, quiz);
  return quiz;
}

export async function saveTestResult(userId, weekNumber, result) {
  await db.saveQuizResult(userId, weekNumber, result);

  const pointsEarned = result.score * 2;
  const members = await db.getTeamMembers();
  const member = members.find(m => m.id === userId);
  await db.upsertLeaderboardEntry(userId, member?.name || 'Unknown', pointsEarned, 1);

  return { pointsEarned };
}

export async function getTestResult(userId, weekNumber) {
  return db.getQuizResult(userId, weekNumber);
}
