// Exercise 1: fix the broken useFormStatus call site
//
// `ContactFormBroken` calls useFormStatus() in the SAME component that
// renders the <form> — it will always report pending: false. Fix it by
// extracting a child SubmitButton component that calls the hook correctly,
// rendered INSIDE the <form>.
//
// TODO 1: implement isValidFormStatusUsage(tree) — pure logic, no React,
//         modeling whether a hook call site is a valid descendant of a form
// TODO 2: implement SubmitButton — a child component calling useFormStatus()
// TODO 3: fix ContactFormFixed to render <SubmitButton /> inside the <form>

import { useFormStatus } from "react-dom";

// --- broken reference (do not fix this one, read it) ---
function ContactFormBroken() {
  const { pending } = useFormStatus(); // BUG: always false — this component RENDERS the form
  return (
    <form action={async () => {}}>
      <input name="email" />
      <button disabled={pending}>{pending ? "Submitting..." : "Submit"}</button>
    </form>
  );
}

// A simplified tree representation: each node is "componentName" or
// "form" (the <form> element itself), and `parentOf` maps a node to its
// direct parent's name (or null for the root). A hook call site is VALID
// only if it sits on a node that has "form" somewhere among its ancestors
// (not on the "form" node itself, and not on an ancestor OF the form).
interface TreeNode {
  name: string;
  parent: string | null;
}

// TODO 1: pure function — given the full tree (array of nodes) and the name
// of the component where useFormStatus() is called, return true only if
// that component has a "form" ancestor (walk up via `parent` links).
function isValidFormStatusUsage(tree: TreeNode[], callSiteName: string): boolean {
  return false; // TODO: walk up from callSiteName via tree, looking for a node named "form"
}

// TODO 2: implement a child component that correctly calls useFormStatus()
function SubmitButton() {
  // TODO: const { pending } = useFormStatus();
  const pending = false; // placeholder — remove once useFormStatus is wired up
  return <button disabled={pending}>{pending ? "Submitting..." : "Submit"}</button>;
}

// TODO 3: render <SubmitButton /> INSIDE the <form>, not a raw <button>
function ContactFormFixed() {
  return (
    <form action={async () => {}}>
      <input name="email" />
      {/* TODO: replace with <SubmitButton /> */}
      <button>Submit</button>
    </form>
  );
}

export { ContactFormBroken, ContactFormFixed, SubmitButton, isValidFormStatusUsage };

// --- self-check: do not modify below this line ---
const tree: TreeNode[] = [
  { name: "ContactFormFixed", parent: null },
  { name: "form", parent: "ContactFormFixed" },
  { name: "SubmitButton", parent: "form" },
];

const check1 = isValidFormStatusUsage(tree, "SubmitButton") === true; // descendant of form: valid
const check2 = isValidFormStatusUsage(tree, "ContactFormFixed") === false; // renders the form: invalid
console.log(check1 ? "PASS (SubmitButton is a valid call site)" : "FAIL (SubmitButton is a valid call site)");
console.log(check2 ? "PASS (ContactFormFixed is an invalid call site)" : "FAIL (ContactFormFixed is an invalid call site)");

// Verify visually: mount <ContactFormBroken /> and <ContactFormFixed />, wire
// each form's action to an async function with a simulated delay
// (await new Promise(r => setTimeout(r, 1000))), then submit both. The
// Broken button never disables itself. The Fixed button (via SubmitButton)
// should disable and show "Submitting..." for the duration of the delay.
