import { anthropic, MODELS } from '../lib/anthropic.js';
import {
  CONTENT_SCHEMAS,
  TYPE_LABELS,
  type MicroLearningType,
  type TopicRecord,
} from '../types.js';

const SYSTEM_PROMPT = `You are a learning content designer. Your task is to generate structured learning content for a specific topic in an employee learning platform.

Output ONLY valid JSON matching the schema provided. No preamble, no explanation, no markdown fences.

The content should be accurate, practical, and appropriate for the stated difficulty level. Tone: professional but accessible.`;

function buildUserPrompt(
  topic: TopicRecord,
  type: MicroLearningType,
  schemaDescription: string,
  strict: boolean,
): string {
  const base = `Topic: ${topic.title}
Difficulty: ${topic.difficulty}
Body:
${topic.body}

Key terms: ${topic.key_terms.join(', ')}

Generate a ${TYPE_LABELS[type]} for this topic.

Output schema:
${schemaDescription}`;

  return strict ? base + '\n\nRespond with valid JSON only, no other text.' : base;
}

const SCHEMA_DESCRIPTIONS: Record<MicroLearningType, string> = {
  concept_explainer: `{
  "paragraphs": ["2 to 3 paragraphs explaining the concept in plain language"],
  "example": "one concrete real-world example"
}`,
  scenario_quiz: `{
  "scenario": "a realistic workplace scenario",
  "options": [
    { "label": "A", "text": "answer text", "correct": false, "explanation": "why" },
    { "label": "B", "text": "answer text", "correct": true,  "explanation": "why" },
    { "label": "C", "text": "answer text", "correct": false, "explanation": "why" },
    { "label": "D", "text": "answer text", "correct": false, "explanation": "why" }
  ]
}
Rules: exactly 4 options, exactly 1 marked correct: true.`,
  misconceptions: `{
  "items": [
    { "misconception": "common wrong belief", "correction": "accurate explanation" }
  ]
}
Rules: 3 to 5 items.`,
  how_to: `{
  "steps": [
    { "number": 1, "instruction": "what to do" }
  ]
}
Rules: 3 to 8 steps.`,
  comparison_card: `{
  "subject_a": "first concept or approach",
  "subject_b": "second concept or approach",
  "dimensions": [
    { "label": "dimension name", "a": "how A differs", "b": "how B differs" }
  ]
}
Rules: 3 to 6 dimensions.`,
  reflection_prompt: `{
  "prompt": "open-ended question for the employee to reflect on",
  "model_answer": "a thoughtful example answer the employee can compare against"
}`,
  flashcard_set: `{
  "cards": [
    { "question": "question text", "answer": "answer text" }
  ]
}
Rules: 5 to 10 cards.`,
  case_study: `{
  "scenario": "a detailed real-world scenario (150+ words)",
  "questions": ["discussion question 1", "discussion question 2"]
}
Rules: 2 to 4 questions.`,
  glossary_anchor: `{
  "term": "the key term",
  "definition": "precise definition",
  "correct_use": "example sentence showing correct use",
  "misuse": "common incorrect usage to avoid"
}`,
  myth_vs_evidence: `{
  "myth": "a commonly held misconception about this topic",
  "evidence": "the evidence-based counterpoint",
  "sources": ["source or reference if applicable — use empty array if none"]
}`,
};

async function callClaude(prompt: string): Promise<string> {
  const response = await anthropic.messages.create({
    model: MODELS.SONNET,
    max_tokens: 2000,
    temperature: 0,
    system: SYSTEM_PROMPT,
    messages: [{ role: 'user', content: prompt }],
  });

  const block = response.content[0];
  if (!block || block.type !== 'text') {
    throw new Error('unexpected response format from Claude');
  }
  return block.text;
}

async function parseAndValidate(raw: string, type: MicroLearningType): Promise<unknown> {
  const schema = CONTENT_SCHEMAS[type];
  const parsed: unknown = JSON.parse(raw);
  return schema.parse(parsed);
}

export async function generateMicroLearning(
  topic: TopicRecord,
  type: MicroLearningType,
): Promise<unknown> {
  const schemaDesc = SCHEMA_DESCRIPTIONS[type];

  // For glossary_anchor, hint Claude to use the first key term
  const topicWithHint: TopicRecord =
    type === 'glossary_anchor' && topic.key_terms.length > 0
      ? { ...topic, body: topic.body + `\n\nAnchor term: ${topic.key_terms[0]}` }
      : topic;

  const prompt = buildUserPrompt(topicWithHint, type, schemaDesc, false);

  let raw: string;
  try {
    raw = await callClaude(prompt);
  } catch (err) {
    throw new Error(`Claude API error: ${err instanceof Error ? err.message : String(err)}`);
  }

  // First parse attempt
  try {
    return await parseAndValidate(raw, type);
  } catch {
    // Retry with strict prompt
    const strictPrompt = buildUserPrompt(topicWithHint, type, schemaDesc, true);
    let raw2: string;
    try {
      raw2 = await callClaude(strictPrompt);
    } catch (err) {
      throw new Error(`Claude API error on retry: ${err instanceof Error ? err.message : String(err)}`);
    }

    try {
      return await parseAndValidate(raw2, type);
    } catch (err) {
      throw new Error(
        `validation failed after retry: ${err instanceof Error ? err.message : String(err)}`,
      );
    }
  }
}
