/* @vitest-environment jsdom */

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

import { BrowserDetector } from "@/utils/browser-detect";
import { PlatformDetector } from "@/utils/platform-detect";
import { pwaUtil } from "@/utils/pwa";

import { FavoriteEntryButton } from "../favorite-entry-button";

describe("FavoriteEntryButton install flow", () => {
  let container: HTMLDivElement;
  let root: Root;

  beforeEach(() => {
    (globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean })
      .IS_REACT_ACT_ENVIRONMENT = true;
    window.localStorage.setItem("cozsweet:favorite_entry", "1");
    vi.spyOn(BrowserDetector, "isInAppBrowser").mockReturnValue(false);
    vi.spyOn(pwaUtil, "isInstalled").mockReturnValue(false);
    vi.spyOn(pwaUtil, "prepareInstallPrompt").mockImplementation(() => undefined);
    vi.spyOn(pwaUtil, "subscribe").mockReturnValue(() => undefined);
    container = document.createElement("div");
    document.body.append(container);
    root = createRoot(container);
  });

  afterEach(() => {
    act(() => root.unmount());
    container.remove();
    window.localStorage.clear();
    vi.restoreAllMocks();
  });

  it("shows Download on iOS and opens Safari add-to-home instructions", () => {
    vi.spyOn(PlatformDetector, "isIOS").mockReturnValue(true);
    vi.spyOn(PlatformDetector, "isAndroid").mockReturnValue(false);

    renderButton();
    const downloadButton = getButton("Download");
    act(() => downloadButton.click());

    expect(container.querySelector('[role="dialog"]')).not.toBeNull();
    expect(container.textContent).toContain("Add CozSweet to Home Screen");
    expect(container.textContent).toContain(
      "In Safari, tap the Share button, then choose “Add to Home Screen”.",
    );
  });

  it("opens the native Android install prompt and marks an accepted install as Saved", async () => {
    vi.spyOn(PlatformDetector, "isIOS").mockReturnValue(false);
    vi.spyOn(PlatformDetector, "isAndroid").mockReturnValue(true);
    const install = vi.spyOn(pwaUtil, "install").mockResolvedValue("accepted");

    renderButton();
    await act(async () => {
      getButton("Download").click();
      await Promise.resolve();
    });

    expect(install).toHaveBeenCalledTimes(1);
    expect(getButton("Saved")).not.toBeNull();
  });

  function renderButton(): void {
    act(() => {
      root.render(<FavoriteEntryButton characterSlug="elio" />);
    });
  }

  function getButton(label: string): HTMLButtonElement {
    const button = container.querySelector<HTMLButtonElement>(
      `button[aria-label="${label}"]`,
    );
    if (!button) throw new Error(`Missing button: ${label}`);
    return button;
  }
});
