/* eslint-disable import-x/order */
import { render, screen, waitFor } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { useAuthStore } from '@/lib/auth-store';

const mockReplace = vi.fn();
let mockSearchParams = new URLSearchParams();

vi.mock('next/navigation', () => ({
  useRouter: () => ({ replace: mockReplace, push: vi.fn() }),
  useSearchParams: () => mockSearchParams,
}));

vi.mock('lucide-react', () => ({
  Loader2: ({ className }: { className?: string }) => <div data-testid="loader" className={className} />,
}));

vi.mock('@/lib/auth-store', () => {
  const store = {
    handleOAuthCallback: vi.fn(),
  };
  return {
    useAuthStore: vi.fn((selector) => {
      if (typeof selector === 'function') return selector(store);
      return store;
    }),
  };
});

import GoogleCallbackPage from '../google/page';

const mockedUseAuthStore = vi.mocked(useAuthStore);

describe('GoogleCallbackPage', () => {
  let mockStore: { handleOAuthCallback: ReturnType<typeof vi.fn> };

  beforeEach(() => {
    vi.clearAllMocks();
    mockStore = {
      handleOAuthCallback: vi.fn().mockResolvedValue(undefined),
    };
    mockedUseAuthStore.mockImplementation((selector) => {
      if (typeof selector === 'function') return (selector as unknown as (s: typeof mockStore) => unknown)(mockStore);
      return mockStore as ReturnType<typeof useAuthStore>;
    });
  });

  it('renders loading spinner and text', () => {
    mockSearchParams = new URLSearchParams();
    render(<GoogleCallbackPage />);
    expect(screen.getByTestId('loader')).toBeInTheDocument();
    expect(screen.getByText(/đang xử lý đăng nhập google/i)).toBeInTheDocument();
  });

  it('redirects to login on error param', async () => {
    mockSearchParams = new URLSearchParams('error=access_denied');
    render(<GoogleCallbackPage />);

    await waitFor(() => {
      expect(mockReplace).toHaveBeenCalledWith('/login?error=access_denied');
    });
  });

  it('redirects to login when tokens are missing', async () => {
    mockSearchParams = new URLSearchParams();
    render(<GoogleCallbackPage />);

    await waitFor(() => {
      expect(mockReplace).toHaveBeenCalledWith('/login?error=oauth_failed');
    });
  });

  it('calls handleOAuthCallback with tokens', async () => {
    mockSearchParams = new URLSearchParams('accessToken=abc&refreshToken=def&expiresIn=3600');
    render(<GoogleCallbackPage />);

    await waitFor(() => {
      expect(mockStore.handleOAuthCallback).toHaveBeenCalledWith('abc', 'def', 3600);
    });
  });
});
