// Exercise 1: class lifecycle order, driven by hand (no real DOM needed)
//
// Class lifecycle methods are just ordinary methods on an ordinary class
// instance — you don't need React, a DOM, or a test renderer to observe
// the ORDER they run in. This exercise drives them directly.
//
// STEPS:
// 1. Implement class LifecycleLogger below:
//    - constructor(props: { log: string[] }): call super(props), then push
//      "constructor" onto props.log.
//    - render(): push "render" onto this.props.log, return null (content
//      doesn't matter for this exercise).
//    - componentDidMount(): push "componentDidMount" onto this.props.log.
//    - componentDidUpdate(): push "componentDidUpdate" onto this.props.log.
//    - componentWillUnmount(): push "componentWillUnmount" onto
//      this.props.log.
// 2. Implement runLifecycle(log): construct one LifecycleLogger instance
//    with { log }, then call its methods in the ORDER React actually
//    calls them for one mount, one update, and then an unmount:
//      construct -> render -> componentDidMount
//                -> render -> componentDidUpdate   (simulating one update)
//                -> componentWillUnmount
//    (See the "Component lifecycle" theory, section 2 and the Quick
//    Reference table, for why this is the correct order per phase.)

import { Component } from "react";

type LoggerProps = { log: string[] };

class LifecycleLogger extends Component<LoggerProps> {
  constructor(props: LoggerProps) {
    super(props);
    // TODO: props.log.push("constructor")
  }

  componentDidMount() {
    // TODO
  }

  componentDidUpdate() {
    // TODO
  }

  componentWillUnmount() {
    // TODO
  }

  render() {
    // TODO: push "render" onto this.props.log, then return null
    return null;
  }
}

function runLifecycle(log: string[]): void {
  // TODO: construct a LifecycleLogger({ log }) and call its methods, in
  // order, to simulate: mount, one update, then unmount.
}

// --- self-check: do not modify below this line ---
const log: string[] = [];
runLifecycle(log);

console.log("recorded order:", log);

const expected = [
  "constructor",
  "render",
  "componentDidMount",
  "render",
  "componentDidUpdate",
  "componentWillUnmount",
];
const orderOk = JSON.stringify(log) === JSON.stringify(expected);
console.log("lifecycle order matches mount->update->unmount:", orderOk ? "PASS" : "FAIL");

// componentDidMount must fire exactly once, no matter how many later
// updates happen — it is NOT the same as "runs on every render."
const mountCount = log.filter((entry) => entry === "componentDidMount").length;
console.log("componentDidMount fires exactly once:", mountCount === 1 ? "PASS" : "FAIL");
