import { expect, test, vi } from "vitest";
import { screen, within } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

import { renderApp } from "../test/render";
import { LabelledRecordRow, type RecordLike } from "./labelled-record-row";
import { HttpError } from "../api/queries";

const record: RecordLike = { id: "r1", external_uri: null, labels: [{ lang: "en", label: "Bronze" }] };

test("edit → save calls onSave and closes via done()", async () => {
  const onSave = vi.fn((_labels: unknown, _uri: unknown, done: () => void) => done());
  renderApp(
    <ul>
      <LabelledRecordRow
        record={record}
        lang="en"
        deleteConfirmKey="actions.confirmDeleteTerm"
        savePending={false}
        saveError={null}
        onEditOpen={() => {}}
        onSave={onSave}
        onDelete={async () => {}}
      />
    </ul>,
  );
  await userEvent.click(screen.getByRole("button", { name: /edit/i }));
  await userEvent.click(screen.getByRole("button", { name: /save/i }));
  expect(onSave).toHaveBeenCalled();
  expect(screen.queryByRole("button", { name: /save/i })).toBeNull();
});

test("a save error renders inline and the row stays editable", async () => {
  renderApp(
    <ul>
      <LabelledRecordRow
        record={record}
        lang="en"
        deleteConfirmKey="actions.confirmDeleteTerm"
        savePending={false}
        saveError={new HttpError(403)}
        onEditOpen={() => {}}
        onSave={() => {}}
        onDelete={async () => {}}
      />
    </ul>,
  );
  await userEvent.click(screen.getByRole("button", { name: /edit/i }));
  expect(screen.getByRole("alert")).toHaveTextContent(/permission/i);
  expect(screen.getByRole("button", { name: /save/i })).toBeInTheDocument();
});

test("confirming delete invokes onDelete", async () => {
  const onDelete = vi.fn(async () => {});
  renderApp(
    <ul>
      <LabelledRecordRow
        record={record}
        lang="en"
        deleteConfirmKey="actions.confirmDeleteTerm"
        savePending={false}
        saveError={null}
        onEditOpen={() => {}}
        onSave={() => {}}
        onDelete={onDelete}
      />
    </ul>,
  );
  await userEvent.click(screen.getByRole("button", { name: /delete/i }));
  const dialog = within(document.body);
  const confirmButtons = await dialog.findAllByRole("button", { name: /delete/i });
  await userEvent.click(confirmButtons[confirmButtons.length - 1]);
  expect(onDelete).toHaveBeenCalled();
});
