/**
 * @vitest-environment jsdom
 */
import {
  cleanup,
  fireEvent,
  render,
  screen,
  waitFor,
} from "@testing-library/react";
import { Popover } from "@workspace/ui/components/popover";
import { afterEach, describe, expect, it, vi } from "vitest";
import { RemarkForm } from "./remark-form";

afterEach(() => {
  cleanup();
});

function renderRemarkForm(props: Parameters<typeof RemarkForm>[0]) {
  return render(
    <Popover open>
      <RemarkForm {...props} />
    </Popover>
  );
}

describe("RemarkForm", () => {
  it("submits an intentionally cleared remark", async () => {
    const onSave = vi.fn<Parameters<typeof RemarkForm>[0]["onSave"]>();

    renderRemarkForm({ initialRemark: "old remark", onSave });

    fireEvent.change(screen.getByPlaceholderText("在此输入备注..."), {
      target: { value: "" },
    });
    fireEvent.click(screen.getByRole("button", { name: "保存" }));

    await waitFor(() => expect(onSave).toHaveBeenCalledWith(""));
  });

  it("shows loading and keeps the input disabled while saving", async () => {
    let resolveSave: (() => void) | undefined;
    const onSave = vi.fn(
      () =>
        new Promise<void>((resolve) => {
          resolveSave = resolve;
        })
    );

    renderRemarkForm({ initialRemark: "old remark", onSave });

    fireEvent.click(screen.getByRole("button", { name: "保存" }));

    expect(
      screen.getByRole("button", { name: "保存中..." }).hasAttribute("disabled")
    ).toBe(true);
    expect(
      screen.getByPlaceholderText("在此输入备注...").hasAttribute("disabled")
    ).toBe(true);

    resolveSave?.();
    await waitFor(() =>
      expect(
        screen.getByRole("button", { name: "保存" }).hasAttribute("disabled")
      ).toBe(false)
    );
  });

  it("shows an error state and preserves input after save failure", async () => {
    const onSave = vi.fn<Parameters<typeof RemarkForm>[0]["onSave"]>();
    onSave.mockRejectedValue(new Error("failed"));

    renderRemarkForm({ initialRemark: "old remark", onSave });

    fireEvent.change(screen.getByPlaceholderText("在此输入备注..."), {
      target: { value: "kept remark" },
    });
    fireEvent.click(screen.getByRole("button", { name: "保存" }));

    expect((await screen.findByRole("alert")).textContent).toBe(
      "备注保存失败，请重试"
    );
    expect(screen.getByDisplayValue("kept remark")).not.toBeNull();
  });
});
