// @vitest-environment happy-dom
(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT =
  true;

import React, { act, useState } from "react";
import { describe, expect, it, vi, beforeEach, afterEach } from "vitest";
import { createRoot, type Root } from "react-dom/client";
import { ExportBar } from "./ExportBar";

function renderBar(
  props: Partial<React.ComponentProps<typeof ExportBar>> = {},
): {
  container: HTMLDivElement;
  unmount: () => void;
} {
  const container = document.createElement("div");
  document.body.appendChild(container);
  const root: Root = createRoot(container);
  const onToggleAll = props.onToggleAll ?? (() => {});
  const onExport = props.onExport ?? (() => {});
  act(() => {
    root.render(
      React.createElement(ExportBar, {
        total: 10,
        selectedCount: 10,
        exporting: false,
        onToggleAll,
        onExport,
        ...props,
      }),
    );
  });
  return {
    container,
    unmount: () => {
      act(() => root.unmount());
      container.remove();
    },
  };
}

describe("ExportBar", () => {
  beforeEach(() => {
    vi.useRealTimers();
  });
  afterEach(() => {
    vi.restoreAllMocks();
  });

  it("renders the total and selected count", () => {
    const { container, unmount } = renderBar({ total: 24, selectedCount: 18 });
    expect(container.textContent).toContain("18");
    expect(container.textContent).toContain("24");
    unmount();
  });

  it("the select-all checkbox is checked when all items are selected", () => {
    const { container, unmount } = renderBar({ total: 5, selectedCount: 5 });
    const cb = container.querySelector<HTMLInputElement>(
      'input[type="checkbox"]',
    )!;
    expect(cb.checked).toBe(true);
    expect(cb.indeterminate).toBe(false);
    unmount();
  });

  it("the select-all checkbox is unchecked when nothing is selected", () => {
    const { container, unmount } = renderBar({ total: 5, selectedCount: 0 });
    const cb = container.querySelector<HTMLInputElement>(
      'input[type="checkbox"]',
    )!;
    expect(cb.checked).toBe(false);
    expect(cb.indeterminate).toBe(false);
    unmount();
  });

  it("the select-all checkbox is indeterminate when some items are selected", () => {
    const { container, unmount } = renderBar({ total: 5, selectedCount: 2 });
    const cb = container.querySelector<HTMLInputElement>(
      'input[type="checkbox"]',
    )!;
    expect(cb.checked).toBe(false);
    expect(cb.indeterminate).toBe(true);
    unmount();
  });

  it("clicking the select-all checkbox calls onToggleAll", () => {
    const onToggleAll = vi.fn();
    const { container, unmount } = renderBar({ onToggleAll });
    const cb = container.querySelector<HTMLInputElement>(
      'input[type="checkbox"]',
    )!;
    act(() => {
      cb.click();
    });
    expect(onToggleAll).toHaveBeenCalledTimes(1);
    unmount();
  });

  it("the export button is disabled when selectedCount is 0", () => {
    const { container, unmount } = renderBar({ selectedCount: 0 });
    const btn = container.querySelector<HTMLButtonElement>("button")!;
    expect(btn.disabled).toBe(true);
    unmount();
  });

  it("the export button is enabled when selectedCount > 0", () => {
    const { container, unmount } = renderBar({ selectedCount: 3 });
    const btn = container.querySelector<HTMLButtonElement>("button")!;
    expect(btn.disabled).toBe(false);
    unmount();
  });

  it("the export button is disabled while exporting", () => {
    const { container, unmount } = renderBar({ selectedCount: 3, exporting: true });
    const btn = container.querySelector<HTMLButtonElement>("button")!;
    expect(btn.disabled).toBe(true);
    unmount();
  });

  it("clicking the export button calls onExport", () => {
    const onExport = vi.fn();
    const { container, unmount } = renderBar({ onExport, selectedCount: 3 });
    const btn = container.querySelector<HTMLButtonElement>("button")!;
    act(() => {
      btn.click();
    });
    expect(onExport).toHaveBeenCalledTimes(1);
    unmount();
  });

  it("renders the selected count in the export button label", () => {
    const { container, unmount } = renderBar({ selectedCount: 7 });
    const btn = container.querySelector<HTMLButtonElement>("button")!;
    expect(btn.textContent).toContain("7");
    unmount();
  });
});
