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

describe("ProtectedRoute", () => {
  beforeEach(() => {
    localStorage.setItem("xtablo-has-seen-landing-page", "true");
  });
  afterEach(() => {
    localStorage.removeItem("xtablo-has-seen-landing-page");
  });

  it("shows loading state initially", () => {
    renderWithRouter(
      <SessionTestProvider>
        <Routes>
          <Route element={<ProtectedRoute />}>
            <Route path="/" element={<div>Protected Content</div>} />
          </Route>
        </Routes>
      </SessionTestProvider>,
      { route: "/" }
    );

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

  it("redirects to login when user is not authenticated", async () => {
    renderWithRouter(
      <TestUserStoreProvider user={null}>
        <SessionTestProvider>
          <Routes>
            <Route element={<ProtectedRoute />}>
              <Route path="/" element={<div>Protected Content</div>} />
            </Route>
            <Route path="/login" element={<div>Login Page</div>} />
          </Routes>
        </SessionTestProvider>
      </TestUserStoreProvider>,
      { route: "/" }
    );

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

  it("redirects to landing page for first-time users", async () => {
    // Set up first-time user scenario
    localStorage.removeItem("xtablo-has-seen-landing-page");

    renderWithRouter(
      <SessionTestProvider>
        <Routes>
          <Route element={<ProtectedRoute />}>
            <Route path="/" element={<div>Protected Content</div>} />
          </Route>
          <Route path="/landing" element={<div>Landing Page</div>} />
        </Routes>
      </SessionTestProvider>,
      { route: "/" }
    );

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

  it("renders protected content when user is authenticated", async () => {
    renderWithRouter(
      <TestUserStoreProvider
        user={{
          id: "123",
          name: "Test User",
          email: "test@example.com",
          avatar_url: "https://example.com/avatar.jpg",
          streamToken: null,
          short_user_id: "123",
          first_name: "Test",
          last_name: "User",
          is_temporary: false,
          last_signed_in: null,
          plan: "none" as const,
          created_at: new Date().toISOString(),
        }}
      >
        <SessionTestProvider>
          <Routes>
            <Route element={<ProtectedRoute />}>
              <Route path="/" element={<div>Protected Content</div>} />
            </Route>
          </Routes>
        </SessionTestProvider>
      </TestUserStoreProvider>,
      { route: "/" }
    );

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

  it("uses custom fallback route when provided", async () => {
    renderWithRouter(
      <SessionTestProvider>
        <Routes>
          <Route element={<ProtectedRoute fallback="/custom-login" />}>
            <Route path="/" element={<div>Protected Content</div>} />
          </Route>
          <Route path="/custom-login" element={<div>Custom Login Page</div>} />
          <Route path="/landing" element={<div>Landing Page</div>} />
        </Routes>
      </SessionTestProvider>,
      { route: "/" }
    );

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