import { describe, it, expect, vi, beforeEach } from "vitest";
import { waitFor } from "@testing-library/react";
import { Notifications } from "@mantine/notifications";
import { matrixServiceMock, runtimeMock, resetWailsMocks } from "../test/mocks/wails";
import { renderWithMantine } from "../test/utils";

vi.mock("../../wailsjs/go/main/MatrixService", () => matrixServiceMock);
vi.mock("../../wailsjs/runtime/runtime", () => runtimeMock);

import HomeScreen from "../HomeScreen";

describe("HomeScreen auto-relogin on stale token", () => {
  beforeEach(() => resetWailsMocks());

  async function expectAutoLogout(errorMessage: string) {
    const onLogout = vi.fn();
    matrixServiceMock.Start.mockRejectedValueOnce(new Error(errorMessage));

    renderWithMantine(
      <>
        <Notifications />
        <HomeScreen userID="@alice:server" onLogout={onLogout} />
      </>,
    );

    await waitFor(() => {
      expect(matrixServiceMock.Logout).toHaveBeenCalledWith("@alice:server");
      expect(onLogout).toHaveBeenCalledTimes(1);
    });
  }

  it("logs out when Start rejects with 'token rejected'", async () => {
    await expectAutoLogout("token rejected by homeserver");
  });

  it("logs out when Start rejects with 'M_UNKNOWN_TOKEN'", async () => {
    await expectAutoLogout("server returned M_UNKNOWN_TOKEN");
  });

  it("does NOT log out for unrelated Start failures", async () => {
    const onLogout = vi.fn();
    matrixServiceMock.Start.mockRejectedValueOnce(new Error("network timeout"));

    renderWithMantine(
      <>
        <Notifications />
        <HomeScreen userID="@alice:server" onLogout={onLogout} />
      </>,
    );

    // Give effect a tick to run.
    await new Promise((r) => setTimeout(r, 30));
    expect(onLogout).not.toHaveBeenCalled();
    expect(matrixServiceMock.Logout).not.toHaveBeenCalled();
  });
});
