import {
  act,
  cleanup,
  fireEvent,
  render,
  screen,
} from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";

import { defineToolcraft } from "../../schema/define-toolcraft";
import type { ToolcraftExternalStore } from "../../state/toolcraft-external-store";
import { ToolcraftRoot } from "./toolcraft-root";
import { useToolcraftStore } from "./toolcraft-store-context";
import { useToolcraftDispatch } from "./use-toolcraft";

const playbackPersistenceSchema = defineToolcraft({
  canvas: { enabled: true },
  panels: { timeline: { mode: "playback" } },
  persistence: {
    include: ["panels", "timeline"],
    key: "toolcraft:playback-boundary:state:v1",
    storage: "localStorage",
    version: 1,
  },
});

function CaptureStore({
  capture,
}: {
  capture: (store: ToolcraftExternalStore) => void;
}): null {
  capture(useToolcraftStore());
  return null;
}

function PublicPlaybackControls(): React.JSX.Element {
  const dispatch = useToolcraftDispatch();

  return (
    <>
      <button
        onClick={() =>
          dispatch({ isPlaying: false, type: "timeline.setPlaying" })
        }
        type="button"
      >
        Pause through public dispatch
      </button>
      <button
        onClick={() => dispatch({ type: "timeline.togglePlayback" })}
        type="button"
      >
        Toggle through public dispatch
      </button>
    </>
  );
}

afterEach(() => {
  vi.useRealTimers();
  cleanup();
  window.localStorage.clear();
});

describe("public playback persistence boundary", () => {
  it.each([
    { buttonName: "Pause through public dispatch", label: "setPlaying(false)" },
    { buttonName: "Toggle through public dispatch", label: "togglePlayback" },
  ])(
    "persists and reloads transient time when public $label stops playback",
    ({ buttonName }) => {
      vi.useFakeTimers();
      let store: ToolcraftExternalStore | undefined;
      const view = render(
        <ToolcraftRoot
          initialState={{ timeline: { isPlaying: true } }}
          schema={playbackPersistenceSchema}
        >
          <CaptureStore capture={(value) => { store = value; }} />
          <PublicPlaybackControls />
        </ToolcraftRoot>,
      );

      act(() => {
        vi.advanceTimersByTime(120);
        store?.dispatchTransient({
          currentTimeSeconds: 2,
          type: "timeline.setCurrentTime",
        });
      });
      fireEvent.click(screen.getByRole("button", { name: buttonName }));

      expect(store?.getCommittedState().timeline).toMatchObject({
        currentTimeSeconds: 2,
        isPlaying: false,
      });

      act(() => {
        vi.advanceTimersByTime(120);
      });
      view.unmount();

      let reloadedStore: ToolcraftExternalStore | undefined;
      render(
        <ToolcraftRoot schema={playbackPersistenceSchema}>
          <CaptureStore capture={(value) => { reloadedStore = value; }} />
        </ToolcraftRoot>,
      );

      expect(reloadedStore?.getState().timeline).toMatchObject({
        currentTimeSeconds: 2,
        isPlaying: false,
      });
    },
  );
});
