// Exercise 1: your first reducer — a pure (state, action) => state function
//
// A reducer is just a plain function. That is the whole point: you can call
// it directly, with no React, no rendering, no DOM — which is exactly what
// the self-check at the bottom does.
//
// STEP 1: implement `counterReducer` so it handles every action in the
//         CounterAction union.
// STEP 2: make sure it NEVER mutates the incoming `state` object — always
//         return a new object.
// STEP 3: wire the component's buttons to `dispatch`.
//
// TODO 1: implement the "increment" / "decrement" / "addAmount" / "reset" cases
// TODO 2: return a NEW object from each case (no `state.count++`)
// TODO 3: dispatch the right action from each button

import { useReducer } from "react";

interface CounterState {
  count: number;
  /** How many actions have been applied so far — proves the reducer ran. */
  applied: number;
}

type CounterAction =
  | { type: "increment" }
  | { type: "decrement" }
  | { type: "addAmount"; amount: number }
  | { type: "reset" };

const initialCounterState: CounterState = { count: 0, applied: 0 };

// TODO 1 + TODO 2: implement all four cases.
// Every returned state must be a brand-new object, and `applied` must go up
// by exactly 1 for every action the reducer handles.
function counterReducer(state: CounterState, action: CounterAction): CounterState {
  switch (action.type) {
    case "increment":
      return state; // TODO: return { count: state.count + 1, applied: state.applied + 1 }
    case "decrement":
      return state; // TODO
    case "addAmount":
      return state; // TODO: add action.amount
    case "reset":
      return state; // TODO: back to count 0, but still count this as an applied action
    default:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(counterReducer, initialCounterState);

  return (
    <div>
      <p>
        count: {state.count} (actions applied: {state.applied})
      </p>
      {/* TODO 3: dispatch the matching action from each button */}
      <button onClick={() => {}}>+1</button>
      <button onClick={() => {}}>-1</button>
      <button onClick={() => {}}>+10</button>
      <button onClick={() => {}}>reset</button>
    </div>
  );
}

export { Counter, counterReducer, initialCounterState };
export type { CounterState, CounterAction };

// --- self-check: do not modify below this line ---
const s0 = initialCounterState;
const s1 = counterReducer(s0, { type: "increment" });
const s2 = counterReducer(s1, { type: "increment" });
const s3 = counterReducer(s2, { type: "addAmount", amount: 10 });
const s4 = counterReducer(s3, { type: "decrement" });
const s5 = counterReducer(s4, { type: "reset" });

const incrementWorks = s1.count === 1 && s2.count === 2;
const addAmountWorks = s3.count === 12;
const decrementWorks = s4.count === 11;
const resetWorks = s5.count === 0;
const countsApplied = s5.applied === 5;

// Purity: the ORIGINAL object must be untouched after five reducer calls.
const didNotMutate = s0.count === 0 && s0.applied === 0;
// New reference every time — React's bailout compares references.
const newReferences = s1 !== s0 && s2 !== s1 && s3 !== s2;
// Same input, same output — a reducer is deterministic.
const deterministic =
  JSON.stringify(counterReducer(s0, { type: "increment" })) ===
  JSON.stringify(counterReducer(s0, { type: "increment" }));

const pass =
  incrementWorks &&
  addAmountWorks &&
  decrementWorks &&
  resetWorks &&
  countsApplied &&
  didNotMutate &&
  newReferences &&
  deterministic;

console.log(pass ? "PASS (counterReducer)" : "FAIL (counterReducer)");
console.log({
  incrementWorks,
  addAmountWorks,
  decrementWorks,
  resetWorks,
  countsApplied,
  didNotMutate,
  newReferences,
  deterministic,
});

// Verify visually: render <Counter />. Every button must change the count on
// screen, and "actions applied" must increase by exactly 1 per click — if it
// jumps by 2 in a dev build under <StrictMode>, your reducer is not pure.
