/**
 * Capture state survives switching away from and back to a session.
 */

// @vitest-environment happy-dom

import { cleanup, render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";

import manifest from "../../fixtures/pdfs/manifest.json" with { type: "json" };

import { captureStateKey, loadCaptureState } from "@app/forms/capture-persistence";

vi.mock("@anchor/index", async (importOriginal) => {
  const original = await importOriginal<typeof import("@anchor/index")>();
  const MockPdfSpikeViewer = () => (
    <div data-testid="mock-pdf-viewer" />
  );
  return { ...original, PdfSpikeViewer: MockPdfSpikeViewer };
});

const FIXTURE = manifest.fixtures.find((f) => f.id === "fristsetzung-bezifferung")!;
const SYNTHETIC_CANONICAL = ["Pre.", FIXTURE.known_good_quote, "Post."].join(" ");
const SESSION_NAME = "capture-persist-session";

import { seedSessionWithDoc } from "./helpers/seed-session";

async function loadApp() {
  const { App } = await import("@app/App");
  return render(<App />);
}

describe("Capture session persistence", () => {
  beforeEach(() => {
    globalThis.localStorage?.clear();
    if (typeof window !== "undefined") {
      history.replaceState(null, "", window.location.pathname);
    }
    seedSessionWithDoc({
      sessionName: SESSION_NAME,
      documentTitle: FIXTURE.filename,
      canonicalText: SYNTHETIC_CANONICAL,
      mode: "forms",
    });
  });

  afterEach(() => {
    vi.restoreAllMocks();
    cleanup();
  });

  it(
    "restores typed field values after leaving and reopening the session",
    { timeout: 20000 },
    async () => {
      const user = userEvent.setup();
      const first = await loadApp();

      const summary = screen.getByLabelText("Summary of the matter");
      await user.type(summary, "Persisted summary text");
      await user.click(screen.getByLabelText("Disputed amount"));

      await waitFor(() => {
        const stored = Object.values(globalThis.localStorage ?? {}).join("");
        expect(stored).toContain("Persisted summary text");
      });

      first.unmount();

      await loadApp();

      const restored = screen.getByLabelText("Summary of the matter") as HTMLTextAreaElement;
      await waitFor(() => {
        expect(restored.value).toBe("Persisted summary text");
      });
    },
  );

  it(
    "writes capture state under the per-session storage key",
    { timeout: 15000 },
    async () => {
      const user = userEvent.setup();
      await loadApp();

      await user.type(screen.getByLabelText("Disputed amount"), "EUR 500");

      await waitFor(() => {
        const keys = Object.keys(globalThis.localStorage ?? {});
        const captureKey = keys.find((k) => k.includes(":capture-state:v1"));
        expect(captureKey).toBeTruthy();
        const sessionId = captureKey!.split(":")[2];
        const state = loadCaptureState(sessionId as never);
        expect(state?.fieldValues.amount).toBe("EUR 500");
        expect(captureStateKey(sessionId as never)).toBe(captureKey);
      });
    },
  );
});