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

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

export function generateIdentityInverse(difficulty: Difficulty): MathProblem {
  const kind = randomChoice(
    difficulty === 1
      ? (["identity-add", "zero", "inverse-add"] as const)
      : (["identity-add", "identity-mul", "zero", "inverse-add"] as const),
  );

  if (kind === "identity-add") {
    const n = randomInt(-20, 20);
    return {
      id: nextId(),
      prompt: `${n} + 0`,
      answer: { kind: "integer", value: n },
      hints: ["0 is the identity for addition.", "Adding 0 changes nothing."],
      steps: [{ explanation: "Adding the identity 0 leaves the number unchanged.", math: `${n} + 0 = ${n}` }],
    };
  }

  if (kind === "identity-mul") {
    const n = randomInt(-20, 20);
    return {
      id: nextId(),
      prompt: `${n} \\times 1`,
      answer: { kind: "integer", value: n },
      hints: ["1 is the identity for multiplication.", "Multiplying by 1 changes nothing."],
      steps: [{ explanation: "Multiplying by the identity 1 leaves the number unchanged.", math: `${n} \\times 1 = ${n}` }],
    };
  }

  if (kind === "zero") {
    const n = randomInt(1, 30);
    return {
      id: nextId(),
      prompt: `${n} \\times 0`,
      answer: { kind: "integer", value: 0 },
      hints: ["Anything multiplied by zero is zero."],
      steps: [{ explanation: "Any number times zero is zero.", math: `${n} \\times 0 = 0` }],
    };
  }

  // inverse-add: additive inverse
  const n = randomInt(-20, 20) || 5;
  return {
    id: nextId(),
    prompt: `\\text{The additive inverse of } ${n} \\text{ is?}`,
    answer: { kind: "integer", value: -n },
    hints: ["The additive inverse adds up to 0.", "Flip the sign."],
    steps: [{ explanation: "The additive inverse flips the sign so the sum is 0.", math: `${n} + (${-n}) = 0` }],
  };
}

export function generateExponentEvaluate(difficulty: Difficulty): MathProblem {
  if (difficulty === 3) {
    // index law: find the resulting exponent
    const base = randomInt(2, 6);
    const op = randomChoice(["\\times", "\\div"] as const);
    if (op === "\\times") {
      const m = randomInt(1, 5);
      const n = randomInt(1, 5);
      return {
        id: nextId(),
        prompt: `${base}^{${m}} \\times ${base}^{${n}} = ${base}^{x}`,
        answer: { kind: "integer", value: m + n },
        hints: ["Same base, multiplying → add the powers.", `${m} + ${n} = ?`],
        steps: [{ explanation: "When multiplying powers of the same base, add the exponents.", math: `${base}^{${m}} \\times ${base}^{${n}} = ${base}^{${m + n}}` }],
      };
    }
    const m = randomInt(3, 7);
    const n = randomInt(1, m - 1);
    return {
      id: nextId(),
      prompt: `${base}^{${m}} \\div ${base}^{${n}} = ${base}^{x}`,
      answer: { kind: "integer", value: m - n },
      hints: ["Same base, dividing → subtract the powers.", `${m} - ${n} = ?`],
      steps: [{ explanation: "When dividing powers of the same base, subtract the exponents.", math: `${base}^{${m}} \\div ${base}^{${n}} = ${base}^{${m - n}}` }],
    };
  }

  if (difficulty === 2 && Math.random() < 0.5) {
    // difference of two powers, e.g. 2^3 - 2^1
    const base = randomInt(2, 4);
    const a = randomInt(2, 3);
    const b = 1;
    const value = Math.pow(base, a) - Math.pow(base, b);
    return {
      id: nextId(),
      prompt: `${base}^{${a}} - ${base}^{${b}}`,
      answer: { kind: "integer", value },
      hints: [`${base}^${a} = ${Math.pow(base, a)}`, `${base}^${b} = ${Math.pow(base, b)}`],
      steps: [{ explanation: "Work out each power, then subtract.", math: `${Math.pow(base, a)} - ${Math.pow(base, b)} = ${value}` }],
    };
  }

  // evaluate a single power (includes n^0 and n^1)
  const base = randomInt(2, difficulty === 1 ? 6 : 9);
  const exp = difficulty === 1 ? randomChoice([0, 1, 2, 2, 3]) : randomChoice([0, 1, 2, 3]);
  const value = Math.pow(base, exp);
  const note = exp === 0 ? "Any number to the power 0 is 1." : exp === 1 ? "Any number to the power 1 is itself." : `Multiply ${base} by itself ${exp} times.`;
  return {
    id: nextId(),
    prompt: `${base}^{${exp}}`,
    answer: { kind: "integer", value },
    hints: [note],
    steps: [{ explanation: note, math: `${base}^{${exp}} = ${value}` }],
  };
}

export function generateDistributive(difficulty: Difficulty): MathProblem {
  const a = randomInt(2, difficulty === 1 ? 6 : 9);
  const b = randomInt(1, difficulty === 1 ? 6 : 9);
  const c = randomInt(1, difficulty === 1 ? 6 : 9);
  const value = a * (b + c);
  return {
    id: nextId(),
    prompt: `${a} \\times (${b} + ${c})`,
    answer: { kind: "integer", value },
    hints: [
      "Add inside the bracket first, then multiply.",
      "Or multiply the outside number by each number inside.",
      `${a} × ${b} + ${a} × ${c}`,
    ],
    steps: [
      { explanation: `Add inside the bracket: ${b} + ${c} = ${b + c}` },
      { explanation: `Multiply: ${a} × ${b + c} = ${value}` },
      { explanation: `Check by distributing: ${a * b} + ${a * c} = ${value}` },
    ],
  };
}
