import { useState } from "react";
import { expect, test } from "vitest";
import { screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { renderApp } from "../test/render";
import { LabelEditor } from "./label-editor";
import type { components } from "../api/schema";

type LabelInput = components["schemas"]["LabelInput"];

function Harness({
  initial = [],
  onChange,
}: {
  initial?: LabelInput[];
  onChange?: (v: LabelInput[]) => void;
}) {
  const [value, setValue] = useState<LabelInput[]>(initial);
  return (
    <LabelEditor
      value={value}
      onChange={(v) => {
        setValue(v);
        onChange?.(v);
      }}
    />
  );
}

test("emits a single label at the instance default language", async () => {
  const seen: LabelInput[][] = [];
  renderApp(<Harness onChange={(v) => seen.push(v)} />);
  await userEvent.type(screen.getByLabelText(/^label$/i), "Brons");
  await waitFor(() => {
    const last = seen[seen.length - 1]!;
    expect(last).toEqual([{ lang: "sv", label: "Brons" }]);
  });
});

test("clearing the input emits an empty array", async () => {
  const seen: LabelInput[][] = [];
  renderApp(<Harness onChange={(v) => seen.push(v)} />);
  const input = screen.getByLabelText(/^label$/i);
  await userEvent.type(input, "X");
  await userEvent.clear(input);
  await waitFor(() => expect(seen[seen.length - 1]).toEqual([]));
});

test("editing preserves labels in other languages", async () => {
  const seen: LabelInput[][] = [];
  renderApp(
    <Harness
      initial={[
        { lang: "en", label: "Bronze" },
        { lang: "sv", label: "Brons" },
      ]}
      onChange={(v) => seen.push(v)}
    />,
  );
  const input = screen.getByLabelText(/^label$/i);
  expect((input as HTMLInputElement).value).toBe("Brons");
  await userEvent.clear(input);
  await userEvent.type(input, "Brons (ny)");
  await waitFor(() => {
    expect(seen[seen.length - 1]).toEqual([
      { lang: "en", label: "Bronze" },
      { lang: "sv", label: "Brons (ny)" },
    ]);
  });
});

test("shows a hint when the entry has labels in other languages", () => {
  renderApp(
    <Harness
      initial={[
        { lang: "en", label: "Bronze" },
        { lang: "sv", label: "Brons" },
      ]}
    />,
  );
  expect(screen.getByText(/other languages/i)).toBeInTheDocument();
});

test("no hint when only the default-language label exists", () => {
  renderApp(<Harness initial={[{ lang: "sv", label: "Brons" }]} />);
  expect(screen.queryByText(/other languages/i)).not.toBeInTheDocument();
});

test("each LabelEditor instance gets a unique input id", () => {
  renderApp(
    <>
      <LabelEditor value={[]} onChange={() => {}} />
      <LabelEditor value={[]} onChange={() => {}} />
    </>,
  );
  const inputs = screen.getAllByLabelText(/label/i);
  expect(inputs).toHaveLength(2);
  expect(inputs[0].id).not.toBe("");
  expect(inputs[0].id).not.toBe(inputs[1].id);
});
