import type { MathProblem, Difficulty } from "../types";
import { randomInt, randomChoice } from "@/lib/utils";
import { simplifyRatio, divideInRatio } from "@/lib/math/ratios";

let counter = 0;
function nextId() {
  return `rp-${++counter}-${Date.now()}`;
}

export function generateDefineRatio(difficulty: Difficulty): MathProblem {
  const contexts = [
    { a: "red", b: "blue", item: "counters in a bag" },
    { a: "boys", b: "girls", item: "in the class" },
    { a: "cats", b: "dogs", item: "at the shelter" },
    { a: "apples", b: "oranges", item: "in the basket" },
  ];
  const ctx = randomChoice(contexts);
  const g = randomChoice(difficulty === 1 ? [1, 2] : difficulty === 2 ? [2, 3, 4] : [3, 4, 5, 6]);
  const x = randomInt(1, difficulty === 1 ? 6 : 8) * g;
  const y = randomInt(1, difficulty === 1 ? 6 : 8) * g;
  const simplified = simplifyRatio([x, y]);

  return {
    id: nextId(),
    prompt: `\\begin{array}{l}\\text{There are ${x} ${ctx.a} and ${y} ${ctx.b} ${ctx.item}.}\\\\\\text{Write the ratio of ${ctx.a} to ${ctx.b} in its simplest form.}\\end{array}`,
    answer: { kind: "ratio", parts: simplified },
    hints: [
      `Write it as ${x} : ${y} first.`,
      "Divide both parts by their highest common factor.",
    ],
    steps: [
      { explanation: `The ratio of ${ctx.a} to ${ctx.b} is ${x} : ${y}.` },
      { explanation: `In simplest form: ${simplified.join(" : ")}` },
    ],
  };
}

export function generateFractionsAndRatios(difficulty: Difficulty): MathProblem {
  const a = randomInt(1, difficulty === 1 ? 4 : 7);
  const b = randomInt(1, difficulty === 1 ? 4 : 7);
  const whole = a + b;
  const which = randomChoice([0, 1] as const);
  const part = which === 0 ? a : b;
  const [n, d] = simplifyRatio([part, whole]);

  return {
    id: nextId(),
    prompt: `\\begin{array}{l}\\text{Two amounts are shared in the ratio } ${a} : ${b}.\\\\\\text{What fraction of the whole is the ${which === 0 ? "first" : "second"} part?}\\end{array}`,
    answer: { kind: "fraction", numerator: n, denominator: d },
    hints: [
      `The whole is ${a} + ${b} = ${whole} parts.`,
      `The ${which === 0 ? "first" : "second"} part is ${part} out of ${whole}.`,
      "Simplify the fraction.",
    ],
    steps: [
      { explanation: `Total parts: ${a} + ${b} = ${whole}.` },
      { explanation: `Fraction = ${part}/${whole}, which simplifies to ${n}/${d}.` },
    ],
  };
}

export function generateSimplifyRatio(difficulty: Difficulty): MathProblem {
  const gcd = randomChoice(difficulty === 1 ? [2, 3, 4, 5] : difficulty === 2 ? [3, 4, 5, 6, 7] : [4, 6, 8, 9, 12]);
  const a = randomInt(1, difficulty === 1 ? 5 : 10) * gcd;
  const b = randomInt(1, difficulty === 1 ? 5 : 10) * gcd;

  const simplified = simplifyRatio([a, b]);

  return {
    id: nextId(),
    prompt: `\\text{Simplify the ratio } ${a}:${b}`,
    answer: { kind: "ratio", parts: simplified },
    hints: [
      `Find the GCD of ${a} and ${b}`,
      `The GCD is ${gcd}`,
      `Divide both parts by ${gcd}`,
    ],
    steps: [
      { explanation: `GCD of ${a} and ${b} is ${gcd}` },
      { explanation: `${a} ÷ ${gcd} = ${simplified[0]}, ${b} ÷ ${gcd} = ${simplified[1]}` },
      { explanation: `Simplified: ${simplified.join(":")}` },
    ],
  };
}

export function generateDivideInRatio(difficulty: Difficulty): MathProblem {
  const numParts = difficulty === 3 ? 3 : 2;
  const parts: number[] = [];
  for (let i = 0; i < numParts; i++) {
    parts.push(randomInt(1, difficulty === 1 ? 5 : 9));
  }

  const sum = parts.reduce((a, b) => a + b, 0);
  const multiplier = randomChoice(difficulty === 1 ? [2, 3, 4, 5] : [3, 4, 5, 6, 7, 8]);
  const total = sum * multiplier;

  const values = divideInRatio(total, parts);
  const intValues = values.map(Math.round);

  const names = ["first share", "second share", "third share"];

  return {
    id: nextId(),
    prompt: `\\text{Share } ${total} \\text{ in the ratio } ${parts.join(":")}`,
    answer: { kind: "ratio", parts: intValues },
    hints: [
      `Total parts: ${parts.join(" + ")} = ${sum}`,
      `One part = ${total} ÷ ${sum} = ${multiplier}`,
      `Multiply each ratio number by ${multiplier}`,
    ],
    steps: [
      { explanation: `Total parts = ${parts.join(" + ")} = ${sum}` },
      { explanation: `One part = ${total} ÷ ${sum} = ${multiplier}` },
      ...parts.map((p, i) => ({
        explanation: `${names[i]}: ${p} × ${multiplier} = ${intValues[i]}`,
      })),
    ],
  };
}

export function generateRatioWordProblem(difficulty: Difficulty): MathProblem {
  const a = randomInt(2, 7);
  const b = randomInt(2, 7);
  const diff = Math.abs(a - b);

  if (diff === 0) {
    return generateDivideInRatio(difficulty);
  }

  const contexts = [
    { item: "sweets", nameA: "Josh", nameB: "Nathan" },
    { item: "marbles", nameA: "Amy", nameB: "Ben" },
    { item: "stickers", nameA: "Karen", nameB: "Natasha" },
  ];
  const ctx = randomChoice(contexts);

  const onePart = randomChoice(difficulty === 1 ? [5, 10, 12] : [6, 8, 9, 15, 20]);
  const extraAmount = diff * onePart;
  const totalParts = a + b;
  const total = totalParts * onePart;

  const bigger = a > b ? ctx.nameA : ctx.nameB;
  const biggerRatio = Math.max(a, b);
  const smallerRatio = Math.min(a, b);

  return {
    id: nextId(),
    prompt: `\\begin{array}{l}\\text{${ctx.item.charAt(0).toUpperCase() + ctx.item.slice(1)} were shared between ${ctx.nameA} and ${ctx.nameB}}\\\\\\text{in the ratio ${a}:${b}. If ${bigger} received ${extraAmount} more ${ctx.item}, find the total shared.}\\end{array}`,
    answer: { kind: "integer", value: total },
    hints: [
      `The difference in ratio parts is ${biggerRatio} - ${smallerRatio} = ${diff}`,
      `${diff} parts = ${extraAmount}, so 1 part = ${onePart}`,
      `Total parts = ${a} + ${b} = ${totalParts}`,
    ],
    steps: [
      { explanation: `Difference in parts: ${biggerRatio} - ${smallerRatio} = ${diff}` },
      { explanation: `${diff} parts = ${extraAmount}, so 1 part = ${extraAmount} ÷ ${diff} = ${onePart}` },
      { explanation: `Total parts: ${a} + ${b} = ${totalParts}` },
      { explanation: `Total ${ctx.item}: ${totalParts} × ${onePart} = ${total}` },
    ],
  };
}
