import { fireEvent, screen, waitFor } from "@testing-library/react";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { renderWithProviders } from "../test/testHelpers";
import { SetPasswordPage } from "./SetPasswordPage";

const { mockSignInWithPassword, mockUpdateUser, mockNavigate } = vi.hoisted(() => ({
  mockSignInWithPassword: vi.fn(),
  mockUpdateUser: vi.fn(),
  mockNavigate: vi.fn(),
}));

vi.mock("../lib/supabase", () => ({
  supabase: {
    auth: {
      signInWithPassword: mockSignInWithPassword,
      updateUser: mockUpdateUser,
    },
  },
}));

vi.mock("react-router-dom", async (importOriginal) => {
  const actual = await importOriginal<typeof import("react-router-dom")>();
  return {
    ...actual,
    useNavigate: () => mockNavigate,
  };
});

describe("SetPasswordPage", () => {
  beforeEach(() => {
    vi.clearAllMocks();
    vi.stubGlobal("fetch", vi.fn());
    mockSignInWithPassword.mockResolvedValue({ data: {}, error: null });
    mockUpdateUser.mockResolvedValue({ data: {}, error: null });
  });

  it("renders an invalid-token state when invite validation fails", async () => {
    vi.mocked(fetch).mockResolvedValueOnce(
      new Response(JSON.stringify({ error: "Invite not found or already used" }), { status: 404 })
    );

    renderWithProviders(<SetPasswordPage />, {
      route: "/set-password?token=bad-token",
      path: "/set-password",
      testUser: undefined,
    });

    await waitFor(() => {
      expect(screen.getByText(/lien invalide/i)).toBeInTheDocument();
    });
  });

  it("submits invite-based password setup once", async () => {
    vi.mocked(fetch)
      .mockResolvedValueOnce(
        new Response(JSON.stringify({ email: "client@example.com", tabloId: "tablo-1" }), {
          status: 200,
        })
      )
      .mockResolvedValueOnce(
        new Response(
          JSON.stringify({ success: true, email: "client@example.com", tabloId: "tablo-1" }),
          {
            status: 200,
          }
        )
      );

    renderWithProviders(<SetPasswordPage />, {
      route: "/set-password?token=good-token",
      path: "/set-password",
      testUser: undefined,
    });

    await waitFor(() => {
      expect(screen.getByLabelText("Mot de passe")).toBeInTheDocument();
    });

    fireEvent.change(screen.getByLabelText("Mot de passe"), { target: { value: "password123" } });
    fireEvent.change(screen.getByLabelText("Confirmer le mot de passe"), {
      target: { value: "password123" },
    });
    fireEvent.click(screen.getByRole("button", { name: "Définir mon mot de passe" }));

    await waitFor(() => {
      expect(fetch).toHaveBeenCalledTimes(2);
      expect(mockSignInWithPassword).toHaveBeenCalledWith({
        email: "client@example.com",
        password: "password123",
      });
      expect(mockNavigate).toHaveBeenCalledWith("/tablo/tablo-1");
    });
  });
});
