const rand = (a, b) => Math.floor(Math.random() * (b - a + 1)) + a;
const pick = arr => arr[Math.floor(Math.random() * arr.length)];
const shuffle = arr => {
  const a = [...arr];
  for (let i = a.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [a[i], a[j]] = [a[j], a[i]];
  }
  return a;
};

function makeQ(question, correct, wrongs) {
  const ca = String(correct);
  const ws = [...new Set(wrongs.map(String))].filter(w => w !== ca);
  const choices = shuffle([ca, ...ws]);
  return { question, choices, correct: choices.indexOf(ca), layout: choices.length === 3 ? 'list' : 'grid' };
}

const g3s1 = [
  () => { const p1 = rand(15,85), p2 = rand(10,75), t = p1+p2; const item1 = pick(['a pencil','an eraser','a ruler','a bookmark']), item2 = pick(['a sticker','a crayon','a marker','a folder']); return makeQ(`Sasha buys ${item1} for ${p1}¢ and ${item2} for ${p2}¢. How much does she pay altogether?`, `${t}¢`, [`${t+rand(5,15)}¢`,`${t-rand(3,10)}¢`,`${t+rand(20,35)}¢`]); },
  () => { const w = rand(2,6), t = w*7; return makeQ(`How many days are in ${w} weeks?`, t, [t+7, t-7, t+rand(1,3)]); },
  () => { const step = pick([2,5,10,3]), start = rand(1,8)*step, seq = [start,start+step,start+2*step,start+3*step], next = start+4*step; return makeQ(`What is the next number in this pattern?\n${seq.join(', ')}, ____`, next, [next+step, next-step, next+2*step]); },
  () => { const l = rand(3,12), w2 = rand(2,9), p = 2*(l+w2); return makeQ(`A rectangle is ${l} cm long and ${w2} cm wide. What is its perimeter?`, `${p} cm`, [`${p+4} cm`,`${p-4} cm`,`${l*w2} cm`]); },
  () => { const d = pick([2,3,4,6,8]), n = rand(1,d-1); return makeQ(`A pizza is cut into ${d} equal slices. ${n} slice${n>1?'s are':' is'} eaten. What fraction has been eaten?`, `${n}/${d}`, [`${n+1}/${d}`,`${n}/${d+1}`,`${d-n}/${d}`]); },
  () => { const g = rand(3,8), e = rand(2,9), t = g*e; const item = pick(['apples','books','stickers','marbles']); return makeQ(`There are ${g} bags with ${e} ${item} in each bag. How many ${item} are there in total?`, t, [t+e, t-e, g+e]); },
  () => { const [obj,unit,w1,w2,w3] = pick([['the length of a room','metres','centimetres','kilometres','millimetres'],['the weight of a watermelon','kilograms','grams','litres','metres'],['the length of an ant','millimetres','metres','kilometres','kilograms'],['the amount of water in a bathtub','litres','kilograms','metres','grams']]); return makeQ(`Which unit would you use to measure ${obj}?`, unit, [w1,w2,w3]); },
  () => { const sh = rand(8,11), dur = rand(1,4), eh = sh+dur; const item = pick(['movie','soccer game','music class','swimming lesson']); return makeQ(`A ${item} starts at ${sh}:00 and ends at ${eh}:00. How long does it last?`, `${dur} hour${dur>1?'s':''}`, [`${dur+1} hours`,`${dur>1?dur-1:dur+2} hours`,`${dur+2} hours`]); },
  () => { const total = rand(40,120), used = rand(10,total-10), left = total-used; const item = pick(['stickers','crayons','cards','beads']); return makeQ(`Jamal had ${total} ${item}. He gave ${used} to his friend. How many does he have now?`, left, [left+rand(5,10), left>5?left-rand(3,5):left+15, total+used]); },
  () => { const n = rand(10,99); const isEven = n%2===0; return makeQ(`Is the number ${n} even or odd?`, isEven?'Even':'Odd', isEven?['Odd','Neither','Both']:['Even','Neither','Both']); },
  () => { const animals=['dogs','cats','birds'], counts=[rand(3,9),rand(3,9),rand(3,9)], total=counts.reduce((a,b)=>a+b,0), table=animals.map((a,i)=>`${a}: ${counts[i]}`).join(' | '); return makeQ(`A survey counted pets:\n${table}\nHow many pets were counted in total?`, total, [total+rand(2,8), total-rand(2,5), counts[0]+counts[1]]); },
];

const g3s2 = [
  () => { const l = rand(3,7), w2 = rand(2,6), area = l*w2; return makeQ(`A rectangle is ${l} units long and ${w2} units wide. What is its area?`, `${area} square units`, [`${area+l} square units`,`${2*(l+w2)} square units`,`${area-w2} square units`]); },
  () => { const start = rand(2,15), rule = rand(3,9), seq = [start,start+rule,start+2*rule,start+3*rule]; return makeQ(`This pattern follows a rule: ${seq.join(', ')} ...\nWhat is the rule?`, `Add ${rule}`, [`Add ${rule+1}`,`Add ${rule-1}`,`Multiply by 2`]); },
  () => { const b = pick([4,6,8]); const a = rand(1,b-1); const d = pick([4,6,8]); let c = rand(1,d-1); let tries=0; while(a*d===c*b && tries<20){c=rand(1,d-1);tries++;} const bigger = a/b>c/d?`${a}/${b}`:`${c}/${d}`, smaller = a/b>c/d?`${c}/${d}`:`${a}/${b}`; return makeQ(`Which fraction is larger: ${a}/${b} or ${c}/${d}?`, bigger, [smaller,'They are equal','Cannot tell']); },
  () => { const [shape,faces] = pick([['cube',6],['rectangular prism',6],['triangular prism',5],['square pyramid',5]]); return makeQ(`How many faces does a ${shape} have?`, faces, [faces+1, faces-1, faces+2]); },
  () => { const a = rand(3,9), b = rand(3,9), product = a*b; return makeQ(`What is ${a} × ${b}?`, product, [product+b, product-a, (a+1)*b]); },
  () => { const price = rand(25,95), paid = Math.ceil(price/25)*25+25, change = paid-price; return makeQ(`An item costs ${price}¢. You pay ${paid}¢. How much change do you get?`, `${change}¢`, [`${change+5}¢`,`${change-5}¢`,`${change+10}¢`]); },
  () => { const sh = rand(9,12), m = pick([0,30]), dur = rand(1,3), eh = sh+dur; const fmt = (h,mm) => `${h}:${mm===0?'00':mm}`; return makeQ(`A library visit starts at ${fmt(sh,m)} and lasts ${dur} hour${dur>1?'s':''}. What time does it end?`, fmt(eh,m), [fmt(eh+1,m),fmt(eh-1,m),fmt(eh,m===0?30:0)]); },
  () => { const rows = rand(3,6), cols = rand(3,6), extra = rand(2,8), total = rows*cols+extra; const item = pick(['chairs','books','tiles','eggs']); return makeQ(`There are ${rows} rows of ${cols} ${item} and ${extra} more on the side. How many ${item} altogether?`, total, [rows*cols, total+extra, total-rows]); },
  () => { const n = rand(12,97), rounded = Math.round(n/10)*10; return makeQ(`Round ${n} to the nearest 10.`, rounded, [rounded+10, rounded-10>=0?rounded-10:rounded+20, n]); },
  () => { const n = rand(2,10)*4, quarter = n/4; return makeQ(`What is one quarter of ${n}?`, quarter, [n/2, quarter*3, quarter+1]); },
  () => { const a = rand(100,499), b = rand(100,499), total = a+b; return makeQ(`What is ${a} + ${b}?`, total, [total+10, total-10, total+100]); },
];

const g6s1 = [
  () => { const rate = rand(3,12), time = rand(4,10), total = rate*time; const item = pick(['pages','laps','problems','push-ups']); return makeQ(`Priya reads ${rate} ${item} per hour. How many will she read in ${time} hours?`, total, [total+rate, total-rate, rate+time]); },
  () => { const pct = pick([10,20,25,50]), whole = rand(2,20)*10, result = whole*pct/100; return makeQ(`What is ${pct}% of ${whole}?`, result, [result+5, result*2, whole-result]); },
  () => { const base = rand(4,14)*2, height = rand(3,10)*2, area = (base*height)/2; return makeQ(`A triangle has a base of ${base} cm and a height of ${height} cm. What is its area?`, `${area} cm²`, [`${base*height} cm²`,`${area+base} cm²`,`${area-height} cm²`]); },
  () => { const bp = rand(2,5), rp = rand(2,5), mult = rand(2,5), blue = bp*mult, red = rp*mult; return makeQ(`For every ${bp} blue marbles there are ${rp} red marbles. If there are ${blue} blue marbles, how many red marbles are there?`, red, [red+rp, red-rp, red+mult]); },
  () => { const a = rand(2,8), b = rand(2,6), c = rand(2,10), result = a+b*c; return makeQ(`Evaluate: ${a} + ${b} × ${c}`, result, [(a+b)*c, result+b, result-a]); },
  () => { const l = rand(2,8), w2 = rand(2,6), h = rand(2,5), vol = l*w2*h; return makeQ(`What is the volume of a rectangular prism with length ${l} cm, width ${w2} cm, and height ${h} cm?`, `${vol} cm³`, [`${vol+l*w2} cm³`,`${2*(l*w2+l*h+w2*h)} cm³`,`${l+w2+h} cm³`]); },
  () => { const d = pick([2,3,4,5]), whole = d*rand(3,8), result = whole/d; return makeQ(`What is 1/${d} of ${whole}?`, result, [result+d, result*d, result-1]); },
  () => { const a = rand(-8,-1), b = rand(1,10), sum = a+b; return makeQ(`What is ${a} + ${b}?`, sum, [sum+2, sum-2, Math.abs(a)+b]); },
  () => { const vals = [rand(4,12),rand(4,12),rand(4,12),rand(4,12)]; const s = vals.reduce((a,b)=>a+b,0); const adj = s%4; if(adj!==0) vals[3]+=4-adj; const s2 = vals.reduce((a,b)=>a+b,0), mean = s2/4; return makeQ(`Find the mean of: ${vals.join(', ')}`, mean, [mean+2, mean-1, s2]); },
  () => { const side = rand(3,15), perim = 4*side; return makeQ(`A square has a perimeter of ${perim} cm. What is the length of one side?`, `${side} cm`, [`${side+2} cm`,`${side-1} cm`,`${perim/2} cm`]); },
  () => { const a = rand(1,9)+rand(1,9)/10, b = rand(1,9)+rand(1,9)/10, total = Math.round((a+b)*10)/10; return makeQ(`What is ${a.toFixed(1)} + ${b.toFixed(1)}?`, total.toFixed(1), [(total+0.5).toFixed(1),(total-0.3).toFixed(1),(total+1).toFixed(1)]); },
];

const g6s2 = [
  () => { const total = rand(4,20)*10, pct = pick([10,20,25,50]), part = total*pct/100; return makeQ(`In a class of ${total} students, ${pct}% walk to school. How many students walk?`, part, [part+5, part-5, total-part]); },
  () => { const km = rand(2,15), m = km*1000; return makeQ(`A hiking trail is ${km} km long. How many metres is this?`, `${m} m`, [`${m+100} m`,`${km*100} m`,`${m-500} m`]); },
  () => { const x = rand(3,15), mult = rand(2,6), product = mult*x; return makeQ(`Solve for n:  ${mult}n = ${product}`, x, [x+1, x-1, mult+x]); },
  () => { const total = pick([4,5,6,8,10]), fav = rand(1,total-1); return makeQ(`A bag has ${total} marbles: ${fav} red and ${total-fav} blue. What is the probability of picking red?`, `${fav}/${total}`, [`${fav+1}/${total}`,`${total-fav}/${total}`,`${fav}/${total-1}`]); },
  () => { const deg = pick([30,45,60,90,120,150]); const type = deg<90?'acute':deg===90?'right':'obtuse'; return makeQ(`An angle measures ${deg}°. What type of angle is it?`, type, ['acute','right','obtuse','reflex'].filter(t=>t!==type).slice(0,3)); },
  () => { const boys = rand(3,8), girls = rand(3,8), total = boys+girls; return makeQ(`The ratio of boys to girls is ${boys}:${girls}. What fraction of the group are boys?`, `${boys}/${total}`, [`${boys}/${girls}`,`${girls}/${total}`,`${boys+1}/${total}`]); },
  () => { const base = pick([2,3,4,5]), exp = pick([2,3]), result = Math.pow(base,exp); return makeQ(`What is ${base}^${exp}?`, result, [base*exp, result+base, result-base]); },
  () => { const d = pick([4,6,8,12]); const n1 = rand(Math.floor(d/2)+1,d-1), n2 = rand(1,Math.floor(d/2)), diff = n1-n2; const gcd = (a,b) => b===0?a:gcd(b,a%b); const g = gcd(diff,d); const ans = `${diff/g}/${d/g}`; return makeQ(`What is ${n1}/${d} − ${n2}/${d}? (simplify if possible)`, ans, [`${diff+1}/${d}`,`${n1}/${d}`,`${diff}/${d+2}`]); },
  () => { const r = rand(3,10), circ = Math.round(2*3.14*r); return makeQ(`A circle has radius ${r} cm. What is its approximate circumference? (π ≈ 3.14)`, `${circ} cm`, [`${Math.round(3.14*r*r)} cm`,`${circ+6} cm`,`${Math.round(2*3.14*(r+1))} cm`]); },
  () => { const rise = rand(1,5), run = rand(1,5); return makeQ(`A line rises ${rise} units for every ${run} units to the right. What is the slope?`, `${rise}/${run}`, [`${run}/${rise}`,`${rise+1}/${run}`,`${rise}/${run+1}`]); },
  () => { const original = rand(4,20)*10, discount = pick([10,20,25]), saved = original*discount/100, final = original-saved; return makeQ(`A jacket costs $${original}. It is ${discount}% off. What is the sale price?`, `$${final}`, [`$${saved}`,`$${final+10}`,`$${final-5}`]); },
];

const g9s1 = [
  () => { const x = rand(2,12), a = rand(2,7), b = rand(1,20), lhs = a*x+b; return makeQ(`Solve for x: ${a}x + ${b} = ${lhs}`, `x = ${x}`, [`x = ${x+1}`,`x = ${x-1}`,`x = ${lhs}`]); },
  () => { const [a,b,c] = pick([[3,4,5],[5,12,13],[8,15,17],[6,8,10]]); return makeQ(`A right triangle has legs of ${a} and ${b}. What is the hypotenuse?`, c, [c+1, c-1, a+b]); },
  () => { const x1=rand(0,4),y1=rand(0,4),rise=rand(1,5),run=rand(1,5); return makeQ(`Find the slope of the line through (${x1}, ${y1}) and (${x1+run}, ${y1+rise}).`, `${rise}/${run}`, [`${run}/${rise}`,`${rise+1}/${run}`,`-${rise}/${run}`]); },
  () => { const a = rand(2,6), b = rand(1,8); return makeQ(`Expand: ${a}(x + ${b})`, `${a}x + ${a*b}`, [`${a}x + ${b}`,`${a+b}x`,`${a}x + ${a*b+1}`]); },
  () => { const original = rand(4,20)*10, pct = pick([10,15,20,25,30]), increase = original*pct/100, final = original+increase; return makeQ(`A price of $${original} increases by ${pct}%. What is the new price?`, `$${final}`, [`$${final+10}`,`$${original-increase}`,`$${final-5}`]); },
  () => { const a = rand(4,10), b = rand(6,14), h = rand(3,8), area = (a+b)*h/2; return makeQ(`A trapezoid has parallel sides of ${a} cm and ${b} cm, and height ${h} cm. What is its area?`, `${area} cm²`, [`${a*b*h/2} cm²`,`${area+h} cm²`,`${(a+b)*h} cm²`]); },
  () => { const base = pick([2,3,5]), e1 = rand(2,5), e2 = rand(2,4); return makeQ(`Simplify: ${base}^${e1} × ${base}^${e2}`, `${base}^${e1+e2}`, [`${base}^${e1*e2}`,`${base}^${e1+e2+1}`,`${base*2}^${e1+e2}`]); },
  () => { const m = rand(2,5), b = rand(1,8), x = rand(3,8), y = m*x+b; return makeQ(`If y = ${m}x + ${b}, what is y when x = ${x}?`, y, [y+m, y-m, m*x]); },
  () => { const x = rand(3,12), a = rand(2,5), b = rand(1,15), rhs = a*x-b; return makeQ(`Solve for x: ${a}x − ${b} = ${rhs}`, `x = ${x}`, [`x = ${x+1}`,`x = ${x-1}`,`x = ${rhs}`]); },
  () => { const s = rand(3,8), sa = 6*s*s; return makeQ(`A cube has side length ${s} cm. What is its surface area?`, `${sa} cm²`, [`${s*s*s} cm³`,`${sa+s*s} cm²`,`${4*s*s} cm²`]); },
  () => { const die = rand(1,5); const coin = pick(['heads','tails']); return makeQ(`A coin is flipped and a 6-sided die is rolled. What is the probability of getting ${coin} and rolling less than ${die+1}?`, `${die}/12`, [`${die}/6`,`1/${die+1}`,`${die+1}/12`]); },
];

const g9s2 = [
  () => { const r = rand(2,6), s = rand(2,5), bc = r+s, cc = r*s; return makeQ(`Factor: x² + ${bc}x + ${cc}`, `(x + ${r})(x + ${s})`, [`(x + ${bc})(x + 1)`,`(x + ${r+1})(x + ${s-1})`,`(x − ${r})(x − ${s})`]); },
  () => { const p = rand(5,20)*100, rate = pick([5,10,20]), interest = p*rate/100, total = p+interest; return makeQ(`$${p} is invested at ${rate}% simple interest for 1 year. What is the total after 1 year?`, `$${total}`, [`$${interest}`,`$${total+50}`,`$${p*2}`]); },
  () => { const m = rand(1,4), b = rand(-5,8); const bs = b>=0?`+ ${b}`:`− ${Math.abs(b)}`; return makeQ(`What is the y-intercept of y = ${m}x ${bs}?`, `(0, ${b})`, [`(${b}, 0)`,`(0, ${b+1})`,`(${m}, 0)`]); },
  () => { const [a,bc,c] = pick([[3,4,5],[5,12,13],[8,15,17]]); return makeQ(`A right triangle has hypotenuse ${c} and one leg ${a}. What is the other leg?`, bc, [bc+1, bc-1, Math.round(Math.sqrt(c*c+a*a))]); },
  () => { const x = rand(3,10), a = rand(2,5), b = rand(1,10), lhs = a*x+b; return makeQ(`Which value of x satisfies ${a}x + ${b} > ${lhs-1}?`, `x = ${x}`, [`x = ${x-1}`,`x = ${x-2}`,`x = 0`]); },
  () => { const rate = rand(3,8), t1 = rand(2,5), t2 = t1+rand(1,3); return makeQ(`A cyclist travels ${rate*t1} km in ${t1} hours at constant speed. How far in ${t2} hours?`, `${rate*t2} km`, [`${rate*t2+rate} km`,`${rate*t1+t2} km`,`${rate*t2-rate} km`]); },
  () => { const angle = rand(30,80); return makeQ(`Two parallel lines are cut by a transversal. One angle is ${angle}°. What is its co-interior angle?`, `${180-angle}°`, [`${angle}°`,`${180+angle}°`,`${90-angle}°`]); },
  () => { const coeff = rand(1,9), exp2 = rand(3,5), value = coeff*Math.pow(10,exp2); return makeQ(`Which equals ${coeff} × 10^${exp2}?`, String(value), [String(value*10),String(value/10),String(coeff+exp2)]); },
  () => { const r = rand(3,7), h = rand(4,10), vol = Math.round(3.14*r*r*h); return makeQ(`A cylinder has radius ${r} cm and height ${h} cm. Approximate its volume (π ≈ 3.14).`, `${vol} cm³`, [`${Math.round(3.14*r*h)} cm³`,`${Math.round(3.14*2*r*h)} cm³`,`${Math.round(3.14*r*r)} cm³`]); },
  () => { const [trend,desc] = pick([['positive','as x increases, y increases'],['negative','as x increases, y decreases'],['no correlation','x and y show no pattern']]); return makeQ(`A scatter plot shows: ${desc}. What type of correlation is this?`, trend, ['positive','negative','no correlation'].filter(t=>t!==trend)); },
  () => { const a = rand(1,3), b = rand(1,5), x = rand(2,5), result = a*x*x+b*x; return makeQ(`Evaluate ${a}x² + ${b}x when x = ${x}.`, result, [result+b, result-a, a*x+b]); },
];

const QUESTION_BANK = { G3: [...g3s1, ...g3s2], G6: [...g6s1, ...g6s2], G9: [...g9s1, ...g9s2] };
const STAGE_SIZE = 11;

function generateStage(grade, stageNum) {
  return QUESTION_BANK[grade].slice((stageNum - 1) * STAGE_SIZE, stageNum * STAGE_SIZE).map(fn => fn());
}

module.exports = { generateStage, STAGE_SIZE };
