/**
 * #69 lot 3 — the mobile key toolbar.
 *
 * Guards the two properties that make the terminal drivable from a phone:
 * the chips emit the exact byte sequences a physical key would, and tapping one
 * never steals focus from xterm (which would collapse the virtual keyboard).
 */
import { describe, it, expect } from "vitest";
import { fireEvent, render, screen } from "@testing-library/react";

import type { TerminalInputApi } from "@/features/terminals";
import { TerminalKeyBar } from "./TerminalKeyBar";

function mockApi(): TerminalInputApi & { sent: string[]; focused: () => number } {
  const sent: string[] = [];
  let focusCount = 0;
  return {
    sent,
    focused: () => focusCount,
    send: (d) => void sent.push(d),
    focus: () => void focusCount++,
  };
}

describe("TerminalKeyBar", () => {
  it("sends the byte sequence a physical key would emit", () => {
    const api = mockApi();
    render(<TerminalKeyBar api={api} />);

    fireEvent.click(screen.getByRole("button", { name: "Ctrl-C (interrompre)" }));
    fireEvent.click(screen.getByRole("button", { name: "Esc" }));
    fireEvent.click(screen.getByRole("button", { name: "Tab" }));
    fireEvent.click(screen.getByRole("button", { name: "Flèche haut" }));

    expect(api.sent).toEqual(["\x03", "\x1b", "\t", "\x1b[A"]);
  });

  it("emits the CSI sequences for every arrow key", () => {
    const api = mockApi();
    render(<TerminalKeyBar api={api} />);

    for (const name of ["Flèche haut", "Flèche bas", "Flèche gauche", "Flèche droite"]) {
      fireEvent.click(screen.getByRole("button", { name }));
    }

    expect(api.sent).toEqual(["\x1b[A", "\x1b[B", "\x1b[D", "\x1b[C"]);
  });

  it("keeps the virtual keyboard up: cancels the tap's focus shift, refocuses xterm", () => {
    const api = mockApi();
    render(<TerminalKeyBar api={api} />);
    const ctrlC = screen.getByRole("button", { name: "Ctrl-C (interrompre)" });

    // `fireEvent` returns false when the handler called preventDefault — that is
    // what stops the browser blurring xterm's textarea and closing the keyboard.
    expect(fireEvent.pointerDown(ctrlC)).toBe(false);

    fireEvent.click(ctrlC);
    expect(api.focused()).toBe(1);
  });

  it("renders disabled until the terminal reports its input API", () => {
    render(<TerminalKeyBar api={null} />);

    for (const button of screen.getAllByRole("button")) {
      expect((button as HTMLButtonElement).disabled).toBe(true);
    }
  });

  it("exposes the keys as an accessible toolbar", () => {
    const api = mockApi();
    render(<TerminalKeyBar api={api} />);

    expect(screen.getByRole("toolbar", { name: "Touches du terminal" })).toBeTruthy();
  });
});
