import { screen, waitFor } from "@testing-library/react";
import { AuthenticationGateway } from "@ui/components/AuthenticationGateway";
import { SessionTestProvider } from "@xtablo/shared/contexts/SessionContext";
import { Route, Routes } from "react-router-dom";
import { vi } from "vitest";
import { TestUserStoreProvider } from "../providers/UserStoreProvider";
import { renderWithRouter } from "../utils/testHelpers";

const { redirectClientUserToPortal } = vi.hoisted(() => ({
  redirectClientUserToPortal: vi.fn(),
}));

vi.mock("../lib/clientPortal", () => ({
  redirectClientUserToPortal,
}));

describe("PublicRoute", () => {
  it("shows loading state initially", () => {
    renderWithRouter(
      <SessionTestProvider
        testUser={{
          id: "123",
          app_metadata: {},
          user_metadata: {
            full_name: "Test User",
            email: "test@example.com",
            email_verified: true,
            first_name: "Test",
            last_name: "User",
            business_name: "Test Business",
          },
          aud: "authenticated",
          created_at: new Date().toISOString(),
        }}
      >
        <Routes>
          <Route element={<AuthenticationGateway />}>
            <Route path="/login" element={<div>Login Page</div>} />
          </Route>
        </Routes>
      </SessionTestProvider>,
      { route: "/login" }
    );

    // Check if loading spinner is present
    expect(screen.getByRole("status")).toBeInTheDocument();
  });

  it("redirect to home when user is authenticated", async () => {
    renderWithRouter(
      <TestUserStoreProvider
        user={{
          id: "123",
          short_user_id: "123",
          name: "Test User",
          first_name: "Test",
          last_name: "User",
          email: "test@example.com",
          avatar_url: null,
          is_client: false,
          client_onboarded_at: null,
          last_signed_in: null,
          plan: "none" as const,
          created_at: new Date().toISOString(),
        }}
      >
        <SessionTestProvider
          testUser={{
            id: "123",
            app_metadata: {},
            user_metadata: {
              full_name: "Test User",
              email: "test@example.com",
              email_verified: true,
              first_name: "Test",
              last_name: "User",
              business_name: "Test Business",
            },
            aud: "authenticated",
            created_at: new Date().toISOString(),
          }}
        >
          <Routes>
            <Route element={<AuthenticationGateway />}>
              <Route path="/login" element={<div>Login Page</div>} />
            </Route>
            <Route path="/" element={<div>Home Page</div>} />
          </Routes>
        </SessionTestProvider>
      </TestUserStoreProvider>,
      { route: "/login" }
    );

    // Wait for the loading state to finish
    await waitFor(() => {
      expect(screen.getByText("Home Page")).toBeInTheDocument();
    });
  });

  it("redirects authenticated client users to the client portal instead of main auth pages", async () => {
    renderWithRouter(
      <TestUserStoreProvider
        user={{
          id: "123",
          short_user_id: "123",
          name: "Client User",
          first_name: "Client",
          last_name: "User",
          email: "client@example.com",
          avatar_url: null,
          is_client: true,
          client_onboarded_at: new Date().toISOString(),
          last_signed_in: null,
          plan: "none" as const,
          created_at: new Date().toISOString(),
        }}
      >
        <SessionTestProvider
          testUser={{
            id: "123",
            app_metadata: {},
            user_metadata: {
              full_name: "Client User",
              email: "client@example.com",
              email_verified: true,
              first_name: "Client",
              last_name: "User",
            },
            aud: "authenticated",
            created_at: new Date().toISOString(),
          }}
        >
          <Routes>
            <Route element={<AuthenticationGateway />}>
              <Route path="/login" element={<div>Login Page</div>} />
            </Route>
          </Routes>
        </SessionTestProvider>
      </TestUserStoreProvider>,
      { route: "/login" }
    );

    await waitFor(() => {
      expect(redirectClientUserToPortal).toHaveBeenCalledWith("/");
    });
    expect(screen.queryByText("Login Page")).not.toBeInTheDocument();
  });

  it("renders public content when user is not authenticated", async () => {
    renderWithRouter(
      <SessionTestProvider testUser={undefined}>
        <Routes>
          <Route element={<AuthenticationGateway />}>
            <Route path="/login" element={<div>Login Page</div>} />
          </Route>
        </Routes>
      </SessionTestProvider>,
      { route: "/login" }
    );

    // Wait for the loading state to finish
    await waitFor(() => {
      expect(screen.getByText("Login Page")).toBeInTheDocument();
    });
  });
});
