/**
 * Prompt Builder for AI Exercise Generation
 *
 * Creates structured, context-aware prompts for the AI model
 * to generate high-quality mathematical exercises with proper notation.
 */

import { ExerciseType, ExerciseDifficulty, TopicType, ModuleType } from '@prisma/client';

/**
 * AI Exercise Request Interface
 */
export interface AIExerciseRequest {
  topic: TopicType;
  moduleType: ModuleType;
  exerciseType: ExerciseType;
  difficulty: ExerciseDifficulty;
  count?: number | undefined;
  context?: string | undefined;
  concepts?: string[] | undefined;
  learningObjectives?: string[] | undefined;
}

/**
 * Built Prompt Result
 */
export interface BuiltPrompt {
  systemPrompt: string;
  userPrompt: string;
}

/**
 * Notation Rules by Topic
 */
const NOTATION_RULES = {
  VECTORES: `
CRITICAL NOTATION RULES FOR VECTORS:
1. Vector components use SEMICOLON separator: (x; y), (a; b; c), NOT (x, y)
2. Vector notation: \\vec{v}, \\vec{u}, \\vec{AB} with arrow above
3. Vector magnitude: |\\vec{v}| or ||\\vec{v}|| with double bars
4. Unit vectors: \\hat{i}, \\hat{j}, \\hat{k} with hat
5. Dot product: \\vec{u} \\cdot \\vec{v} with cdot
6. Cross product: \\vec{u} \\times \\vec{v} with times
7. Sum/difference: \\vec{u} + \\vec{v}, \\vec{u} - \\vec{v}
8. Scalar multiplication: \\lambda \\vec{v}
9. Position vectors: use \\vec{OA} to denote vector from origin
10. ALWAYS use (x; y; z) format for vector components`,

  MATRICES: `
CRITICAL NOTATION RULES FOR MATRICES:
1. Matrix representation: \\begin{pmatrix} a & b \\\\ c & d \\end{pmatrix}
2. Use pmatrix environment for ALL matrices
3. Determinant notation: |A| or \\det(A)
4. Matrix transpose: A^T or A^{\\top}
5. Identity matrix: I_n with subscript for dimension
6. Zero matrix: O or \\mathbf{0}
7. Matrix multiplication: AB (no dot symbol)
8. Inverse matrix: A^{-1}
9. Use \\begin{bmatrix} ... \\end{bmatrix} for augmented matrices
10. Row operations: use R_1, R_2 notation
11. Determinant expansion: use cofactor notation with proper signs`,

  SISTEMAS: `
CRITICAL NOTATION RULES FOR SYSTEMS:
1. System notation: \\begin{cases} x + y = 5 \\\\ 2x - y = 1 \\end{cases}
2. Variables with subscripts: x_1, x_2, x_3, NOT x1, x2, x3
3. Augmented matrix: \\left[ \\begin{array}{cc|c} 1 & 2 & 3 \\\\ 4 & 5 & 6 \\end{array} \\right]
4. Solution set: \\{(x, y, z) \\in \\mathbb{R}^3 \\mid ... \\}
5. Parameter notation: \\lambda, \\mu for free variables
6. Homogeneous system: Ax = \\vec{0}
7. Consistency: mention unique solution, infinite solutions, or no solution
8. Use t or \\lambda for parameters in solution sets`,

  ESPACIOS_VECTORIALES: `
CRITICAL NOTATION RULES FOR VECTOR SPACES:
1. Space notation: (V; +; \\mathbb{R}; \\cdot) with semicolons
2. Field notation: \\mathbb{R}, \\mathbb{C}, \\mathbb{Q} for number sets
3. Vector addition: + with circle for operations
4. Scalar multiplication: \\cdot for scalar product
5. Subspace notation: W \\subseteq V
6. Basis notation: \\mathcal{B} = \\{\\vec{v}_1, \\vec{v}_2, ...\\}
7. Dimension notation: \\dim(V) with dim function
8. Linear combination: \\sum_{i=1}^{n} \\alpha_i \\vec{v}_i
9. Span notation: \\operatorname{span}(\\vec{v}_1, \\vec{v}_2)
10. Kernel/Null space: \\ker(T) or \\operatorname{Nul}(T)
11. Image/Range: \\operatorname{Im}(T) or \\operatorname{R}(T)
12. Use \\mathcal{B} for basis, \\mathcal{S} for sets`,

  PROGRAMACION_LINEAL: `
CRITICAL NOTATION RULES FOR LINEAR PROGRAMMING:
1. Objective function: Minimizar Z = 3x + 5y or Maximizar P = 2x - y
2. Constraints: use \\le for \\leq and \\ge for \\geq
3. Non-negativity: x \\ge 0, y \\ge 0 for all variables
4. Feasible region: \\mathcal{R} or R
5. Optimal solution: (x^*, y^*) or \\vec{x}^*
6. Slack variables: x_1, x_2 with subscripts
7. Standard form: Ax = b, x \\ge 0
8. Dual problem notation: use "Primal:" and "Dual:" labels
9. Use \\begin{aligned} ... \\end{aligned} for multi-line optimization
10. Corner points: label as V_1, V_2, etc.`,
};

/**
 * Concept Prompts by Topic
 */
const CONCEPT_PROMPTS = {
  VECTORES: [
    'Vector addition and subtraction in R² and R³',
    'Scalar multiplication and its geometric interpretation',
    'Dot product and its applications (angle, orthogonality, projection)',
    'Cross product in R³ and geometric interpretation',
    'Vector magnitude and direction',
    'Unit vectors and direction vectors',
    'Position vectors and displacement',
    'Linear combinations of vectors',
    'Vector equations of lines and planes',
  ],

  MATRICES: [
    'Matrix operations (addition, subtraction, multiplication)',
    'Matrix transpose and symmetric matrices',
    'Determinants of 2x2 and 3x3 matrices',
    'Inverse matrices and conditions for existence',
    'Systems of linear equations using matrices',
    'Row operations and row echelon form',
    'Rank of a matrix',
    'Eigenvalues and eigenvectors',
    'Diagonalization',
    'Matrix transformations',
  ],

  SISTEMAS: [
    'Systems of linear equations in 2 and 3 variables',
    'Consistency and inconsistency of systems',
    'Unique solutions vs infinite solutions vs no solution',
    'Gaussian elimination',
    'Gauss-Jordan elimination',
    'Homogeneous systems',
    'Matrix representation of systems',
    'Cramer\'s rule',
    'Systems with parameters',
  ],

  ESPACIOS_VECTORIALES: [
    'Definition and axioms of vector spaces',
    'Subspaces and subspace tests',
    'Linear independence and dependence',
    'Basis and dimension',
    'Coordinate vectors',
    'Change of basis',
    'Linear transformations',
    'Kernel and image of linear transformations',
    'Rank-nullity theorem',
    'Isomorphisms between vector spaces',
  ],

  PROGRAMACION_LINEAL: [
    'Formulation of linear programming problems',
    'Graphical method for 2-variable problems',
    'Feasible regions and corner points',
    'Simplex method introduction',
    'Standard form conversion',
    'Slack variables',
    'Dual problems',
    'Sensitivity analysis',
    'Applications to optimization',
  ],
};

/**
 * Difficulty Level Descriptions
 */
const DIFFICULTY_DESCRIPTIONS = {
  BASIC: 'BASIC: Direct application of formulas and concepts. Minimal steps. Suitable for beginners just learning the topic.',
  INTERMEDIATE: 'INTERMEDIATE: Requires combining 2-3 concepts. Moderate number of steps. Some algebraic manipulation needed.',
  ADVANCED: 'ADVANCED: Complex multi-step problems. Requires deep understanding of multiple concepts. Significant algebraic manipulation.',
  EXPERT: 'EXPERT: Challenging problems requiring creative thinking. Multiple approaches possible. Integration of various topics. Proof-level reasoning.',
};

/**
 * Exercise Type Instructions
 */
const EXERCISE_TYPE_INSTRUCTIONS = {
  MULTIPLE_CHOICE: `
EXERCISE TYPE: MULTIPLE CHOICE
- Provide 4 options (A, B, C, D)
- Only ONE correct answer
- Include plausible distractors based on common mistakes
- Each option should be a complete mathematical statement or value
- For the correct option, include a brief explanation
- Distractors should be clearly wrong but mathematically valid-looking`,

  OPEN_RESPONSE: `
EXERCISE TYPE: OPEN RESPONSE
- Ask for a complete solution with all steps shown
- Require detailed explanations
- Student must demonstrate the full process
- Include reasoning and justifications
- The answer should be a mathematical expression, value, or statement`,

  CALCULATION: `
EXERCISE TYPE: CALCULATION
- Focus on numerical or symbolic computation
- Provide clear intermediate steps
- Include the final computed result
- Show all algebraic manipulations
- The answer should be a specific value or simplified expression`,

  PROOF: `
EXERCISE TYPE: PROOF
- Require a formal mathematical proof
- State what is given (hypothesis)
- State what needs to be proven (thesis)
- Suggest relevant theorems or properties to use
- Expect a logical, step-by-step argument
- Include conclusion statement`,

  TRUE_FALSE: `
EXERCISE TYPE: TRUE/FALSE
- Provide clear mathematical statements
- Each statement should be unambiguously true or false
- Include justification for the correct answer
- Statements should test conceptual understanding
- Avoid trivial or ambiguous statements`,
};

/**
 * Prompt Builder Class
 */
export class PromptBuilder {
  /**
   * Build complete prompt for exercise generation
   */
  buildExercisePrompt(request: AIExerciseRequest): BuiltPrompt {
    const systemPrompt = this.buildSystemPrompt();
    const userPrompt = this.buildUserPrompt(request);

    return { systemPrompt, userPrompt };
  }

  /**
   * Build system prompt with role and general instructions
   */
  private buildSystemPrompt(): string {
    return `You are an expert mathematics professor specializing in Linear Algebra. You create high-quality educational exercises with precise mathematical notation.

YOUR EXPERTISE:
- Deep knowledge of linear algebra concepts
- Mastery of LaTeX mathematical notation
- Understanding of common student misconceptions
- Ability to create progressive difficulty exercises
- Focus on clarity and mathematical rigor

OUTPUT FORMAT:
You MUST respond with valid JSON containing an "exercises" array. Each exercise must have:
{
  "exercises": [
    {
      "statement": "Complete problem statement with LaTeX",
      "correctAnswer": "The correct answer in LaTeX format",
      "solutionSteps": [
        {"step": 1, "explanation": "Explanation of this step", "latexFormula": "optional LaTeX for this step"},
        ...
      ],
      "formulas": [
        {"latex": "formula in LaTeX", "description": "what the formula represents", "step": 1},
        ...
      ],
      "hints": [
        {"hint": "First hint text", "cost": 2},
        {"hint": "Second hint text", "cost": 3}
      ],
      "multipleChoiceOptions": [
        {"option": "A) \\text{option text}", "isCorrect": false, "explanation": "why this is wrong"},
        {"option": "B) \\text{correct answer}", "isCorrect": true, "explanation": "brief explanation"}
      ],
      "difficulty": "BASIC|INTERMEDIATE|ADVANCED|EXPERT",
      "estimatedTimeSeconds": 300
    }
  ]
}

CRITICAL REQUIREMENTS:
1. ALL mathematical notation must use proper LaTeX
2. Follow specific notation rules for each topic (provided in user prompt)
3. Solution steps must be clear and educational
4. Hints should guide without giving away the answer
5. Difficulty must match the requested level
6. Include relevant formulas used in the solution
7. For proof exercises, include givens and what to prove
8. For multiple choice, provide exactly 4 options

MATH NOTATION STANDARDS:
- Use \\\\ for line breaks in LaTeX
- Use \\begin{cases} ... \\end{cases} for systems
- Use \\begin{pmatrix} ... \\end{pmatrix} for matrices
- Use \\vec{v} for vectors with arrow
- Use ^ for superscripts, _ for subscripts
- Use \\le for ≤, \\ge for ≥
- Use \\in for ∈, \\subset for ⊂
- Use \\mathbb{R} for real numbers set
- Use \\mathcal{B} for script letters

STANDARDS FOR EDUCATIONAL CONTENT:
- Problems should be mathematically correct and verifiable
- Solutions should show complete work
- Explanations should be clear and pedagogical
- Common mistakes should be anticipated in hints
- Difficulty should be consistent within level`;
  }

  /**
   * Build user prompt with specific request details
   */
  private buildUserPrompt(request: AIExerciseRequest): string {
    const count = request.count || 1;
    const notationRules = NOTATION_RULES[request.topic] || '';
    const exerciseTypeInstructions = EXERCISE_TYPE_INSTRUCTIONS[request.exerciseType] || '';
    const difficultyDesc = DIFFICULTY_DESCRIPTIONS[request.difficulty];

    let prompt = `Generate ${count} ${request.exerciseType.replace('_', ' ')} exercise(s) for the topic: ${request.topic}\n\n`;

    prompt += `**MODULE**: ${request.moduleType}\n`;
    prompt += `**DIFFICULTY**: ${request.difficulty} - ${difficultyDesc}\n`;
    prompt += `**EXERCISE TYPE**: ${request.exerciseType}\n\n`;

    if (request.context) {
      prompt += `**CONTEXT**: ${request.context}\n\n`;
    }

    if (request.concepts && request.concepts.length > 0) {
      prompt += `**CONCEPTS TO COVER**:\n`;
      request.concepts.forEach((concept, i) => {
        prompt += `  ${i + 1}. ${concept}\n`;
      });
      prompt += '\n';
    }

    if (request.learningObjectives && request.learningObjectives.length > 0) {
      prompt += `**LEARNING OBJECTIVES**:\n`;
      request.learningObjectives.forEach((obj, i) => {
        prompt += `  ${i + 1}. ${obj}\n`;
      });
      prompt += '\n';
    }

    // Add notation rules
    prompt += `**NOTATION RULES - FOLLOW STRICTLY**:\n${notationRules}\n\n`;

    // Add exercise type instructions
    prompt += `**EXERCISE TYPE INSTRUCTIONS**:\n${exerciseTypeInstructions}\n\n`;

    // Add sample concepts if none provided
    if (!request.concepts || request.concepts.length === 0) {
      const sampleConcepts = this.getRandomConcepts(request.topic, count);
      prompt += `**SUGGESTED CONCEPTS** (you may vary these):\n`;
      sampleConcepts.forEach((concept, i) => {
        prompt += `  ${i + 1}. ${concept}\n`;
      });
      prompt += '\n';
    }

    prompt += `**OUTPUT REQUIREMENTS**:\n`;
    prompt += `1. Return valid JSON only (no markdown formatting, no code blocks)\n`;
    prompt += `2. Include exactly ${count} exercise(s) in the "exercises" array\n`;
    prompt += `3. Each exercise must have all required fields\n`;
    prompt += `4. Follow the notation rules strictly\n`;
    prompt += `5. Ensure all LaTeX is properly formatted\n`;
    prompt += `6. Solution steps should be detailed and educational\n`;
    prompt += `7. Include 2-3 hints per exercise\n`;

    if (request.exerciseType === 'MULTIPLE_CHOICE') {
      prompt += `8. Include exactly 4 multiple choice options per exercise\n`;
    }

    prompt += `\nGenerate the exercises now. Respond with valid JSON only.`;

    return prompt;
  }

  /**
   * Build prompt for exercise regeneration with feedback
   */
  buildRegenerationPrompt(
    originalExercise: any,
    feedback: string
  ): BuiltPrompt {
    const systemPrompt = this.buildSystemPrompt();

    const userPrompt = `REGENERATE this exercise based on the provided feedback.

**ORIGINAL EXERCISE**:
Statement: ${originalExercise.statement}
Answer: ${originalExercise.correctAnswer}
Type: ${originalExercise.type}
Difficulty: ${originalExercise.difficulty}

**FEEDBACK FOR IMPROVEMENT**:
${feedback}

**REQUIREMENTS**:
1. Address the feedback points
2. Maintain the same topic and difficulty level
3. Keep the mathematical concepts consistent
4. Improve clarity or adjust difficulty as indicated
5. Follow all notation rules for the topic
6. Return valid JSON with a single exercise

Generate the improved exercise now. Respond with valid JSON only.`;

    return { systemPrompt, userPrompt };
  }

  /**
   * Build prompt for exercise validation
   */
  buildValidationPrompt(exercise: any): BuiltPrompt {
    const systemPrompt = `You are a mathematics content validator. Your job is to check exercises for mathematical correctness, notation accuracy, and pedagogical quality.`;

    const userPrompt = `Validate this exercise:

**EXERCISE**:
\`\`\`
${JSON.stringify(exercise, null, 2)}
\`\`\`

**VALIDATION CHECKLIST**:
1. Mathematical correctness: Is the answer correct?
2. Notation accuracy: Is LaTeX properly formatted?
3. Clarity: Is the problem statement clear?
4. Solution quality: Are solution steps logical and complete?
5. Difficulty appropriateness: Does it match the stated difficulty?
6. Educational value: Is it useful for learning?

Return JSON:
{
  "isValid": true/false,
  "issues": ["issue1", "issue2", ...],
  "suggestions": ["suggestion1", ...],
  "correctedExercise": {...} // if corrections needed
}`;

    return { systemPrompt, userPrompt };
  }

  /**
   * Build prompt for hint generation
   */
  buildHintPrompt(
    exercise: any,
    currentHints: string[],
    userDifficulty: 'STRUGGLING' | 'PROGRESSING' | 'ADVANCING'
  ): BuiltPrompt {
    const systemPrompt = `You are an expert math tutor. You provide pedagogically appropriate hints that guide students without giving away the answer.`;

    let userPrompt = `Generate additional hints for this exercise based on student performance.

**EXERCISE**:
${exercise.statement}

**CURRENT HINTS**:
${currentHints.map((h, i) => `${i + 1}. ${h}`).join('\n')}

**STUDENT STATUS**: ${userDifficulty}
- STRUGGLING: Needs very guided hints, break down into small steps
- PROGRESSING: Moderate guidance, point in right direction
- ADVANCING: Minimal guidance, subtle suggestions only

**REQUIREMENTS**:
Generate 1-2 new hints that:
1. Are different from existing hints
2. Appropriate for the student's current understanding
3. Guide without revealing the answer
4. Build conceptual understanding

Return JSON:
{
  "hints": [
    {"hint": "hint text", "cost": 2}
  ]
}`;

    return { systemPrompt, userPrompt };
  }

  /**
   * Build prompt for solution explanation
   */
  buildSolutionPrompt(
    exercise: any,
    userAnswer: string,
    isCorrect: boolean
  ): BuiltPrompt {
    const systemPrompt = `You are an encouraging math tutor. You provide clear explanations that help students learn from their mistakes or reinforce correct understanding.`;

    let userPrompt = `Provide feedback on this student's answer.

**EXERCISE**:
${exercise.statement}

**CORRECT ANSWER**:
${exercise.correctAnswer}

**STUDENT ANSWER**:
${userAnswer}

**IS CORRECT**: ${isCorrect}

${isCorrect ? `
**REQUIREMENTS FOR CORRECT ANSWER**:
1. Acknowledge the correct answer
2. Provide brief positive reinforcement
3. Summarize the key approach
4. Suggest a related concept to explore next

Return JSON:
{
  "feedback": "positive message",
  "summary": "brief explanation of approach",
  "nextStep": "suggestion for next learning"
}
` : `
**REQUIREMENTS FOR INCORRECT ANSWER**:
1. Identify where the mistake occurred
2. Explain the correct approach step by step
3. Highlight the misconception
4. Be encouraging and supportive
5. Reference the relevant solution steps

Return JSON:
{
  "feedback": "constructive message",
  "mistakeLocation": "where the error occurred",
  "correctApproach": "step by step explanation",
  "misconception": "what misunderstanding led to this error",
  "encouragement": "motivational message"
}
`}`;

    return { systemPrompt, userPrompt };
  }

  /**
   * Get random concepts for a topic
   */
  private getRandomConcepts(topic: TopicType, count: number): string[] {
    const concepts = CONCEPT_PROMPTS[topic] || [];
    const shuffled = [...concepts].sort(() => Math.random() - 0.5);
    return shuffled.slice(0, Math.min(count, concepts.length));
  }

  /**
   * Build prompt for generating variations of an exercise
   */
  buildVariationPrompt(
    exercise: any,
    variationType: 'NUMBERS' | 'CONTEXT' | 'DIFFICULTY'
  ): BuiltPrompt {
    const systemPrompt = this.buildSystemPrompt();

    const descriptions = {
      NUMBERS: 'Keep the same structure but change the numerical values',
      CONTEXT: 'Keep the same mathematical concept but change the real-world context or scenario',
      DIFFICULTY: 'Create a similar problem but adjust the difficulty level',
    };

    const userPrompt = `Create a variation of this exercise.

**ORIGINAL EXERCISE**:
\`\`\`
${JSON.stringify(exercise, null, 2)}
\`\`\`

**VARIATION TYPE**: ${variationType}
${descriptions[variationType]}

**REQUIREMENTS**:
1. Maintain the same mathematical topic
2. Follow all notation rules
3. Keep the solution structure similar
4. Return valid JSON with a single exercise

Generate the variation now. Respond with valid JSON only.`;

    return { systemPrompt, userPrompt };
  }

  /**
   * Build prompt for exercise difficulty adjustment
   */
  buildDifficultyPrompt(
    exercise: any,
    targetDifficulty: ExerciseDifficulty
  ): BuiltPrompt {
    const systemPrompt = this.buildSystemPrompt();

    const userPrompt = `Adjust this exercise to a different difficulty level.

**ORIGINAL EXERCISE**:
\`\`\`
${JSON.stringify(exercise, null, 2)}
\`\`\`

**TARGET DIFFICULTY**: ${targetDifficulty}
${DIFFICULTY_DESCRIPTIONS[targetDifficulty]}

**REQUIREMENTS**:
1. Keep the same topic and type
2. Adjust complexity to match target difficulty
3. Add or remove solution steps as needed
4. Maintain mathematical correctness
5. Follow all notation rules

Return valid JSON with a single exercise.`;

    return { systemPrompt, userPrompt };
  }

  /**
   * Build prompt for concept-specific exercise generation
   */
  buildConceptPrompt(
    topic: TopicType,
    concept: string,
    difficulty: ExerciseDifficulty,
    count: number
  ): BuiltPrompt {
    const systemPrompt = this.buildSystemPrompt();
    const notationRules = NOTATION_RULES[topic] || '';

    const userPrompt = `Generate ${count} exercise(s) specifically for the concept: "${concept}"

**TOPIC**: ${topic}
**DIFFICULTY**: ${difficulty}
**CONCEPT**: ${concept}

**NOTATION RULES**:
${notationRules}

**REQUIREMENTS**:
1. Focus entirely on the specified concept
2. Create exercises that build understanding from different angles
3. Include progressive complexity within the set
4. Return valid JSON

Generate the exercises now. Respond with valid JSON only.`;

    return { systemPrompt, userPrompt };
  }
}

/**
 * Export singleton instance
 */
export const promptBuilder = new PromptBuilder();

/**
 * Export convenience function
 */
export function buildExercisePrompt(request: AIExerciseRequest): BuiltPrompt {
  return promptBuilder.buildExercisePrompt(request);
}

export default PromptBuilder;
