// packages/feature_game_mathquiz/lib/controllers/math_quiz_generator.dart
import 'dart:math';
import 'package:flutter/material.dart'; // debugPrint 사용을 위해 유지
import 'package:service_api/service_api.dart';
import '../models/math_quiz_difficulty.dart';
import '../models/math_quiz_models.dart';
import 'package:function_tree/function_tree.dart';

class MathQuizGenerator {
  final Random _random = Random();

  /// 문자열이 연산자인지 확인
  bool _isOperator(String value) {
    return ['+', '-', '*', '/'].contains(value);
  }

  /// 난이도에 맞는 퍼즐을 생성합니다.
  MathQuizPuzzle generatePuzzle(MathQuizDifficulty level) {
    switch (level.layout) {
      case MathQuizLayout.singleLine:
        if (level.operationCount == 2) {
          return _generateSimpleEquation(level);
        } else {
          return _generateMultiOpEquation(level);
        }
      case MathQuizLayout.dualLine:
        return _generateDualLineEquation(level);
      case MathQuizLayout.linkedL:
        return _generateLinkedEquations(level);
      case MathQuizLayout.gridSquare:
        if (level.operationCount == 9) {
          return _generate3x3GridEquation(level);
        } else {
          return _generate4x4GridEquation(level);
        }
    }
  }

  /// [Lv 1-3] 숫자 2개 연산: (A op B = C)
  MathQuizPuzzle _generateSimpleEquation(MathQuizDifficulty level) {
    final (int a, int b, int c, String op) = _createEquation(level.operators);
    final List<String> allParts = (op == '+')
        ? [a.toString(), op, b.toString(), '=', c.toString()]
        : (op == '-')
            ? [c.toString(), op, a.toString(), '=', b.toString()]
            : (op == '*')
                ? [a.toString(), op, b.toString(), '=', c.toString()]
                : [c.toString(), op, a.toString(), '=', b.toString()];
    
    debugPrint("--- GEN LOG (Lv 1-3): ALL PARTS: $allParts"); // [LOG]

    List<int> candidateIndices;
    switch (level.blankType) {
      case MathQuizBlankType.numbersOnly: candidateIndices = [0, 2]; break;
      case MathQuizBlankType.operatorsOnly: candidateIndices = [1]; break;
      case MathQuizBlankType.numbersAndOperators: candidateIndices = [0, 1, 2]; break;
    }
    final int finalBlankCount = min(level.blankCount, candidateIndices.length);
    final List<int> blankIndices = (candidateIndices..shuffle(_random)).sublist(0, finalBlankCount);

    blankIndices.sort(); // 👈 FIX

    final List<String> solutions = [];
    final List<PuzzleBlankType> finalBlankTypes = [];
    final List<String> gridCells = List.of(allParts);
    for (int index in blankIndices) {
      final String solutionValue = allParts[index];
      solutions.add(solutionValue);
      finalBlankTypes.add(_isOperator(solutionValue)
          ? PuzzleBlankType.operator
          : PuzzleBlankType.number);
      gridCells[index] = '?';
    }
    
    debugPrint("--- GEN LOG (Lv 1-3): BLANK INDICES: $blankIndices"); // [LOG]
    debugPrint("--- GEN LOG (Lv 1-3): SOLUTIONS: $solutions | TYPES: $finalBlankTypes"); // [LOG]

    final Set<String> optionsSet = solutions.toSet();
    while (optionsSet.length < 9) { optionsSet.add((_random.nextInt(9) + 1).toString()); }
    optionsSet.addAll(level.operators.split(','));
    if (level.blankType != MathQuizBlankType.operatorsOnly) { optionsSet.add('='); }
    final List<String> options = (optionsSet.toList()..shuffle(_random)).toList();

    return MathQuizPuzzle(
      gridCells: gridCells,
      gridCrossAxisCount: 5,
      options: options,
      solutions: solutions,
      blankTypes: finalBlankTypes,
      equations: [
        MathQuizEquation(expressionIndices: [0, 1, 2], resultIndex: 4),
      ],
    );
  }

  /// [Lv 4-6] 숫자 3개 연산: (A op1 B op2 C = D)
  MathQuizPuzzle _generateMultiOpEquation(MathQuizDifficulty level) {
    final (int a, int b, int c, String op1, String op2, int result) = _createMultiOpEquation(level.operators);
    
    // [LOG 1] 튜플 생성 직후 값 확인
    debugPrint("--- GEN LOG: TUPLE: a=$a, op1=$op1, b=$b, op2=$op2, c=$c, R=$result");
    
    final List<String> allParts = [
      a.toString(), 
      op1,          
      b.toString(), 
      op2,          
      c.toString(), 
      '=',          
      result.toString() 
    ];
    
    // [LOG 2] allParts 리스트 완성 직후 값 확인
    debugPrint("--- GEN LOG (Lv 4-6): ALL PARTS: $allParts");
    
    final int blankCount = level.blankCount;
    List<int> candidateIndices;
    switch (level.blankType) {
      case MathQuizBlankType.numbersOnly: candidateIndices = [0, 2, 4]; break;
      case MathQuizBlankType.operatorsOnly: candidateIndices = [1, 3]; break;
      case MathQuizBlankType.numbersAndOperators: candidateIndices = [0, 1, 2, 3, 4]; break;
    }
    final int finalBlankCount = min(blankCount, candidateIndices.length);
    final List<int> blankIndices = (candidateIndices..shuffle(_random)).sublist(0, finalBlankCount);

    blankIndices.sort(); // 👈 FIX
    
    // [LOG 3] blankIndices 리스트 결정 직후 확인
    debugPrint("--- GEN LOG (Lv 4-6): BLANK INDICES: $blankIndices");

    final List<String> solutions = [];
    final List<PuzzleBlankType> finalBlankTypes = [];
    final List<String> gridCells = List.of(allParts);
    for (int index in blankIndices) {
      final String solutionValue = allParts[index];
      solutions.add(solutionValue);
      finalBlankTypes.add(_isOperator(solutionValue)
          ? PuzzleBlankType.operator
          : PuzzleBlankType.number);
      gridCells[index] = '?';
    }
    
    debugPrint("--- GEN LOG (Lv 4-6): SOLUTIONS: $solutions | TYPES: $finalBlankTypes"); // [LOG]


    final Set<String> optionsSet = solutions.toSet();
    while (optionsSet.length < 9) { optionsSet.add((_random.nextInt(9) + 1).toString()); }
    optionsSet.addAll(level.operators.split(','));
    optionsSet.add('=');
    
    return MathQuizPuzzle(
      gridCells: gridCells,
      gridCrossAxisCount: 7,
      options: (optionsSet.toList()..shuffle(_random)).toList(),
      solutions: solutions,
      blankTypes: finalBlankTypes,
      equations: [
        MathQuizEquation(expressionIndices: [0, 1, 2, 3, 4], resultIndex: 6),
      ],
    );
  }

  /// [Lv 7-9] 독립된 2줄 (A op B = C, D op E = F)
  MathQuizPuzzle _generateDualLineEquation(MathQuizDifficulty level) {
    final (int a, int b, int c, String op1) = _createEquation(level.operators);
    final (int d, int e, int f, String op2) = _createEquation(level.operators);
    
    final List<String> allParts = [
      a.toString(), op1, b.toString(), "=", c.toString(),
      " ", " ", " ", " ", " ",
      d.toString(), op2, e.toString(), "=", f.toString(),
    ];
    debugPrint("--- GEN LOG (Lv 7-9 DUAL): ALL PARTS: $allParts"); // [LOG]


    List<int> numberIndices = [0, 2, 10, 12];
    List<int> operatorIndices = [1, 11];
    List<int> blankIndices = [];
    switch (level.blankType) {
      case MathQuizBlankType.numbersOnly:
        blankIndices = (numberIndices..shuffle(_random)).sublist(0, min(level.blankCount, numberIndices.length));
        break;
      case MathQuizBlankType.operatorsOnly:
        blankIndices = (operatorIndices..shuffle(_random)).sublist(0, min(level.blankCount, operatorIndices.length));
        break;
      case MathQuizBlankType.numbersAndOperators:
        blankIndices = (numberIndices + operatorIndices..shuffle(_random)).sublist(0, level.blankCount);
        break;
    }
    
    blankIndices.sort(); // 👈 FIX

    final List<String> solutions = [];
    final List<PuzzleBlankType> finalBlankTypes = [];
    final List<String> gridCells = List.of(allParts);
    for (int index in blankIndices) {
      final String solutionValue = allParts[index];
      solutions.add(solutionValue);
      finalBlankTypes.add(_isOperator(solutionValue)
          ? PuzzleBlankType.operator
          : PuzzleBlankType.number);
      gridCells[index] = '?';
    }
    
    debugPrint("--- GEN LOG (Lv 7-9 DUAL): BLANK INDICES: $blankIndices"); // [LOG]
    debugPrint("--- GEN LOG (Lv 7-9 DUAL): SOLUTIONS: $solutions | TYPES: $finalBlankTypes"); // [LOG]


    final Set<String> optionsSet = solutions.toSet();
    while (optionsSet.length < 9) { optionsSet.add((_random.nextInt(9) + 1).toString()); }
    optionsSet.addAll(level.operators.split(','));
    optionsSet.add('=');

    return MathQuizPuzzle(
      gridCells: gridCells,
      gridCrossAxisCount: 5,
      options: (optionsSet.toList()..shuffle(_random)).toList(),
      solutions: solutions,
      blankTypes: finalBlankTypes,
      equations: [
        MathQuizEquation(expressionIndices: [0, 1, 2], resultIndex: 4),
        MathQuizEquation(expressionIndices: [10, 11, 12], resultIndex: 14),
      ],
    );
  }

  /// [Lv 10-12] 숫자 4개 연산: (2x2 그리드 'ㄱ', 'ㄴ')
  MathQuizPuzzle _generateLinkedEquations(MathQuizDifficulty level) {
    while (true) {
      final int a = _random.nextInt(9) + 1;
      final int b = _random.nextInt(9) + 1;
      final int c = _random.nextInt(9) + 1;
      final int d = _random.nextInt(9) + 1;
      final ops = level.operators.split(',');
      final String op1 = (ops..shuffle(_random)).first;
      final String op2 = (ops..shuffle(_random)).first;
      final String op3 = (ops..shuffle(_random)).first;
      final String op4 = (ops..shuffle(_random)).first;
      final int? r1 = _calculate(a, b, op1);
      final int? r2 = _calculate(c, d, op2);
      final int? r3 = _calculate(a, c, op3);
      final int? r4 = _calculate(b, d, op4);
      if (r1 == null || r2 == null || r3 == null || r4 == null) continue;
      if (r1 < -99 || r2 < -99 || r3 < -99 || r4 < -99 || r1 > 999 || r2 > 999 || r3 > 999 || r4 > 999) continue;
      final List<String> allParts = [
        a.toString(), op1, b.toString(), "=", r1.toString(),
        op3, " ", op4, " ", "=",
        c.toString(), op2, d.toString(), "=", r2.toString(),
        "=", " ", "=", " ", "=",
        r3.toString(), " ", r4.toString(), " ", " ",
      ];
      debugPrint("--- GEN LOG (Lv 10-12 LINKED): ALL PARTS: $allParts"); // [LOG]

      List<int> numberIndices = [0, 2, 10, 12];
      List<int> operatorIndices = [1, 5, 7, 11];
      List<int> blankIndices = [];
      switch (level.blankType) {
        case MathQuizBlankType.numbersOnly:
          blankIndices = (numberIndices..shuffle(_random)).sublist(0, min(level.blankCount, numberIndices.length));
          break;
        case MathQuizBlankType.operatorsOnly:
          blankIndices = (operatorIndices..shuffle(_random)).sublist(0, min(level.blankCount, operatorIndices.length));
          break;
        case MathQuizBlankType.numbersAndOperators:
          blankIndices = (numberIndices + operatorIndices..shuffle(_random)).sublist(0, level.blankCount);
          break;
      }
      
      blankIndices.sort(); // 👈 FIX

      final List<String> solutions = [];
      final List<PuzzleBlankType> finalBlankTypes = [];
      final List<String> gridCells = List.of(allParts);
      for (int index in blankIndices) {
        final String solutionValue = allParts[index];
        solutions.add(solutionValue);
        finalBlankTypes.add(_isOperator(solutionValue)
            ? PuzzleBlankType.operator
            : PuzzleBlankType.number);
        gridCells[index] = '?';
      }
      
      debugPrint("--- GEN LOG (Lv 10-12 LINKED): BLANK INDICES: $blankIndices"); // [LOG]
      debugPrint("--- GEN LOG (Lv 10-12 LINKED): SOLUTIONS: $solutions | TYPES: $finalBlankTypes"); // [LOG]

      final Set<String> optionsSet = solutions.toSet();
      while (optionsSet.length < 9) { optionsSet.add((_random.nextInt(9) + 1).toString()); }
      optionsSet.addAll(level.operators.split(','));
      optionsSet.add('=');

      return MathQuizPuzzle(
        gridCells: gridCells,
        gridCrossAxisCount: 5,
        options: (optionsSet.toList()..shuffle(_random)).toList(),
        solutions: solutions,
        blankTypes: finalBlankTypes,
        equations: [
          MathQuizEquation(expressionIndices: [0, 1, 2], resultIndex: 4),
          MathQuizEquation(expressionIndices: [10, 11, 12], resultIndex: 14),
          MathQuizEquation(expressionIndices: [0, 5, 10], resultIndex: 20),
          MathQuizEquation(expressionIndices: [2, 7, 12], resultIndex: 22),
        ],
      );
    }
  }

  /// [Lv 13-15] 3x3 Grid - 동적 생성
  MathQuizPuzzle _generate3x3GridEquation(MathQuizDifficulty level) {
    while (true) {
      try {
        final ops = level.operators.split(',');
        final n = List.generate(9, (_) => _random.nextInt(9) + 1);
        final o = List.generate(12, (_) => (ops..shuffle(_random)).first);
        final expr = [
          "${n[0]} ${o[0]} ${n[1]} ${o[1]} ${n[2]}", // R0
          "${n[3]} ${o[5]} ${n[4]} ${o[6]} ${n[5]}", // R1
          "${n[6]} ${o[10]} ${n[7]} ${o[11]} ${n[8]}", // R2
          "${n[0]} ${o[2]} ${n[3]} ${o[7]} ${n[6]}", // R3
          "${n[1]} ${o[3]} ${n[4]} ${o[8]} ${n[7]}", // R4
          "${n[2]} ${o[4]} ${n[5]} ${o[9]} ${n[8]}", // R5
        ];
        final List<num> r = expr.map((e) => e.interpret()).toList();
        if (r.any((res) => res.toInt() != res || res < -99 || res > 999)) { continue; }
        final List<int> rInt = r.map((res) => res.toInt()).toList();
        final List<String> allParts = [
          n[0].toString(), o[0], n[1].toString(), o[1], n[2].toString(), "=", rInt[0].toString(),
          o[2], " ", o[3], " ", o[4], " ", "=",
          n[3].toString(), o[5], n[4].toString(), o[6], n[5].toString(), "=", rInt[1].toString(),
          o[7], " ", o[8], " ", o[9], " ", "=",
          n[6].toString(), o[10], n[7].toString(), o[11], n[8].toString(), "=", rInt[2].toString(),
          "=", " ", "=", " ", "=", " ", "=",
          rInt[3].toString(), " ", rInt[4].toString(), " ", rInt[5].toString(), " ", " ",
        ];
        debugPrint("--- GEN LOG (Lv 13-15 Grid): ALL PARTS: $allParts"); // [LOG]


        final List<int> numberIndices = [0, 2, 4, 14, 16, 18, 28, 30, 32];
        final List<int> operatorIndices = [1, 3, 7, 9, 11, 15, 17, 21, 23, 25, 29, 31];
        List<int> blankIndices = [];
        switch (level.blankType) {
          case MathQuizBlankType.numbersOnly:
            blankIndices = (numberIndices..shuffle(_random)).sublist(0, min(level.blankCount, numberIndices.length));
            break;
          case MathQuizBlankType.operatorsOnly:
            blankIndices = (operatorIndices..shuffle(_random)).sublist(0, min(level.blankCount, operatorIndices.length));
            break;
          case MathQuizBlankType.numbersAndOperators:
            blankIndices = (numberIndices + operatorIndices..shuffle(_random)).sublist(0, level.blankCount);
            break;
        }
        
        blankIndices.sort(); // 👈 FIX

        final List<String> solutions = [];
        final List<PuzzleBlankType> finalBlankTypes = [];
        final List<String> gridCells = List.of(allParts);
        for (int index in blankIndices) {
          final String solutionValue = allParts[index];
          solutions.add(solutionValue);
          finalBlankTypes.add(_isOperator(solutionValue)
              ? PuzzleBlankType.operator
              : PuzzleBlankType.number);
          gridCells[index] = '?';
        }
        
        debugPrint("--- GEN LOG (Lv 13-15 Grid): BLANK INDICES: $blankIndices"); // [LOG]
        debugPrint("--- GEN LOG (Lv 13-15 Grid): SOLUTIONS: $solutions | TYPES: $finalBlankTypes"); // [LOG]


        final Set<String> optionsSet = solutions.toSet();
        while (optionsSet.length < 9) { optionsSet.add((_random.nextInt(9) + 1).toString()); }
        optionsSet.addAll(level.operators.split(','));
        optionsSet.add('=');
        final List<String> options = (optionsSet.toList()..shuffle(_random)).toList();

        return MathQuizPuzzle(
          gridCells: gridCells,
          gridCrossAxisCount: 7,
          options: options,
          solutions: solutions,
          blankTypes: finalBlankTypes,
          equations: [
            MathQuizEquation(expressionIndices: [0, 1, 2, 3, 4], resultIndex: 6),
            MathQuizEquation(expressionIndices: [14, 15, 16, 17, 18], resultIndex: 20),
            MathQuizEquation(expressionIndices: [28, 29, 30, 31, 32], resultIndex: 34),
            MathQuizEquation(expressionIndices: [0, 7, 14, 21, 28], resultIndex: 42),
            MathQuizEquation(expressionIndices: [2, 9, 16, 23, 30], resultIndex: 44),
            MathQuizEquation(expressionIndices: [4, 11, 18, 25, 32], resultIndex: 46),
          ],
        );
      } catch (e) {
        continue;
      }
    }
  }

  /// [Lv 16-19] 4x4 Grid - 동적 생성
  MathQuizPuzzle _generate4x4GridEquation(MathQuizDifficulty level) {
    while (true) {
      try {
        final ops = level.operators.split(',');
        final n = List.generate(16, (_) => _random.nextInt(9) + 1);
        final o = List.generate(24, (_) => (ops..shuffle(_random)).first);
        final expr = [
          "${n[0]} ${o[0]} ${n[1]} ${o[1]} ${n[2]} ${o[2]} ${n[3]}", // R0
          "${n[4]} ${o[3]} ${n[5]} ${o[4]} ${n[6]} ${o[5]} ${n[7]}", // R1
          "${n[8]} ${o[6]} ${n[9]} ${o[7]} ${n[10]} ${o[8]} ${n[11]}", // R2
          "${n[12]} ${o[9]} ${n[13]} ${o[10]} ${n[14]} ${o[11]} ${n[15]}", // R3
          "${n[0]} ${o[12]} ${n[4]} ${o[13]} ${n[8]} ${o[14]} ${n[12]}", // R4
          "${n[1]} ${o[15]} ${n[5]} ${o[16]} ${n[9]} ${o[17]} ${n[13]}", // R5
          "${n[2]} ${o[18]} ${n[6]} ${o[19]} ${n[10]} ${o[20]} ${n[14]}", // R6
          "${n[3]} ${o[21]} ${n[7]} ${o[22]} ${n[11]} ${o[23]} ${n[15]}", // R7
        ];
        final List<num> r = expr.map((e) => e.interpret()).toList();
        if (r.any((res) => res.toInt() != res || res < -999 || res > 9999)) { continue; }
        final List<int> rInt = r.map((res) => res.toInt()).toList();
        final List<String> allParts = [
          n[0].toString(), o[0], n[1].toString(), o[1], n[2].toString(), o[2], n[3].toString(), "=", rInt[0].toString(),
          o[12], " ", o[15], " ", o[18], " ", o[21], " ", "=",
          n[4].toString(), o[3], n[5].toString(), o[4], n[6].toString(), o[5], n[7].toString(), "=", rInt[1].toString(),
          o[13], " ", o[16], " ", o[19], " ", o[22], " ", "=",
          n[8].toString(), o[6], n[9].toString(), o[7], n[10].toString(), o[8], n[11].toString(), "=", rInt[2].toString(),
          o[14], " ", o[17], " ", o[20], " ", o[23], " ", "=",
          n[12].toString(), o[9], n[13].toString(), o[10], n[14].toString(), o[11], n[15].toString(), "=", rInt[3].toString(),
          "=", " ", "=", " ", "=", " ", "=", " ", "=",
          rInt[4].toString(), " ", rInt[5].toString(), " ", rInt[6].toString(), " ", rInt[7].toString(), " ", " ",
        ];
        debugPrint("--- GEN LOG (Lv 16-19 Grid): ALL PARTS: $allParts"); // [LOG]


        final List<int> numberIndices = [0, 2, 4, 6, 18, 20, 22, 24, 36, 38, 40, 42, 54, 56, 58, 60];
        final List<int> operatorIndices = [ 1, 3, 5, 9, 11, 13, 15, 19, 21, 23, 27, 29, 31, 33, 37, 39, 41, 45, 47, 49, 51, 55, 57, 59 ];
        List<int> blankIndices = [];
        switch (level.blankType) {
          case MathQuizBlankType.numbersOnly:
            blankIndices = (numberIndices..shuffle(_random)).sublist(0, min(level.blankCount, numberIndices.length));
            break;
          case MathQuizBlankType.operatorsOnly:
            blankIndices = (operatorIndices..shuffle(_random)).sublist(0, min(level.blankCount, operatorIndices.length));
            break;
          case MathQuizBlankType.numbersAndOperators:
            blankIndices = (numberIndices + operatorIndices..shuffle(_random)).sublist(0, level.blankCount);
            break;
        }
        
        blankIndices.sort(); // 👈 FIX

        final List<String> solutions = [];
        final List<PuzzleBlankType> finalBlankTypes = [];
        final List<String> gridCells = List.of(allParts);
        for (int index in blankIndices) {
          final String solutionValue = allParts[index];
          solutions.add(solutionValue);
          finalBlankTypes.add(_isOperator(solutionValue)
              ? PuzzleBlankType.operator
              : PuzzleBlankType.number);
          gridCells[index] = '?';
        }
        
        debugPrint("--- GEN LOG (Lv 16-19 Grid): BLANK INDICES: $blankIndices"); // [LOG]
        debugPrint("--- GEN LOG (Lv 16-19 Grid): SOLUTIONS: $solutions | TYPES: $finalBlankTypes"); // [LOG]


        final Set<String> optionsSet = solutions.toSet();
        while (optionsSet.length < 9) { optionsSet.add((_random.nextInt(9) + 1).toString()); }
        optionsSet.addAll(level.operators.split(','));
        optionsSet.add('=');
        final List<String> options = (optionsSet.toList()..shuffle(_random)).toList();

        return MathQuizPuzzle(
          gridCells: gridCells,
          gridCrossAxisCount: 9,
          options: options,
          solutions: solutions,
          blankTypes: finalBlankTypes,
          equations: [
            MathQuizEquation(expressionIndices: [0, 1, 2, 3, 4, 5, 6], resultIndex: 8),
            MathQuizEquation(expressionIndices: [18, 19, 20, 21, 22, 23, 24], resultIndex: 26),
            MathQuizEquation(expressionIndices: [36, 37, 38, 39, 40, 41, 42], resultIndex: 44),
            MathQuizEquation(expressionIndices: [54, 55, 56, 57, 58, 59, 60], resultIndex: 62),
            MathQuizEquation(expressionIndices: [0, 9, 18, 27, 36, 45, 54], resultIndex: 72),
            MathQuizEquation(expressionIndices: [2, 11, 20, 29, 38, 47, 56], resultIndex: 74),
            MathQuizEquation(expressionIndices: [4, 13, 22, 31, 40, 49, 58], resultIndex: 76),
            MathQuizEquation(expressionIndices: [6, 15, 24, 33, 42, 51, 60], resultIndex: 78),
          ],
        );
      } catch (e) {
        continue;
      }
    }
  }

  // ( ... _createEquation, _createMultiOpEquation, _calculate는 이전과 동일 ... )
 (int, int, int, String) _createEquation(String operators, {int? firstTerm, int maxResult = 9}) {
    final List<String> ops = operators.split(',');
    final String op = ops[_random.nextInt(ops.length)];
    int a, b, c;
    switch (op) {
      case '+': a = firstTerm ?? _random.nextInt(maxResult - 1) + 1; b = _random.nextInt(maxResult - a) + 1; c = a + b; return (a, b, c, op);
      case '-': c = firstTerm ?? _random.nextInt(maxResult - 1) + 2; a = _random.nextInt(c - 1) + 1; b = c - a; return (a, b, c, op);
      case '*': a = firstTerm ?? _random.nextInt(maxResult ~/ 2) + 2; b = _random.nextInt(maxResult ~/ a) + 1; c = a * b; return (a, b, c, op);
      case '/': b = _random.nextInt(maxResult ~/ 2) + 1; a = _random.nextInt(maxResult ~/ b) + 1; c = a * b; if (c == 0 || a == 0) return _createEquation(operators, firstTerm: firstTerm, maxResult: maxResult); return (a, b, c, op);
      default: return (1, 1, 2, '+');
    }
  }
  (int, int, int, String, String, int) _createMultiOpEquation(String operators) {
    while(true) {
      final int a = _random.nextInt(9) + 1;
      final int b = _random.nextInt(9) + 1;
      final int c = _random.nextInt(9) + 1;
      final List<String> ops = operators.split(',');
      final String op1 = (ops..shuffle(_random)).first;
      final String op2 = (ops..shuffle(_random)).first;
      final String expression = "$a $op1 $b $op2 $c";
      try {
        final num resultNum = expression.interpret();
        final int result = resultNum.toInt();
        if (result == resultNum && result >= -99 && result <= 999) {
          return (a, b, c, op1, op2, result);
        }
      } catch (e) {
        continue;
      }
    }
  }
  int? _calculate(int a, int b, String op) {
    switch (op) {
      case '+': return a + b;
      case '-': return a - b;
      case '*': return a * b;
      case '/': if (b == 0) return null; if (a % b != 0) return null; return a ~/ b;
    }
    return 0;
  }
}