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

// Mock next-intl with Vietnamese messages
const viMessages = await import('@/messages/vi.json');
vi.mock('next-intl', () => ({
  useTranslations: (namespace: string) => {
    const messages = viMessages.default ?? viMessages;
    const ns = messages[namespace as keyof typeof messages] as Record<string, unknown> | undefined;
    return (key: string) => {
      if (!ns) return key;
      const parts = key.split('.');
      let val: unknown = ns;
      for (const p of parts) {
        val = (val as Record<string, unknown>)?.[p];
      }
      return typeof val === 'string' ? val : key;
    };
  },
  NextIntlClientProvider: ({ children }: { children: React.ReactNode }) => children,
}));

// Mock next/navigation
const mockPush = vi.fn();
const mockSearchParams = new URLSearchParams();
vi.mock('next/navigation', () => ({
  useRouter: () => ({ push: mockPush }),
  useSearchParams: () => mockSearchParams,
}));

// Mock next/link
vi.mock('next/link', () => ({
  default: ({ children, href, ...props }: { children: React.ReactNode; href: string; [key: string]: unknown }) => (
    <a href={href} {...props}>{children}</a>
  ),
}));

// Mock i18n navigation (Link used in login page)
vi.mock('@/i18n/navigation', () => ({
  Link: ({ children, href, ...props }: { children: React.ReactNode; href: string; [key: string]: unknown }) => (
    <a href={href} {...props}>{children}</a>
  ),
  useRouter: () => ({ push: vi.fn(), replace: vi.fn() }),
  usePathname: () => '/login',
  redirect: vi.fn(),
}));

// Mock auth store
vi.mock('@/lib/auth-store', () => {
  const store = {
    user: null,
    isAuthenticated: false,
    isInitialized: false,
    isLoading: false,
    error: null,
    login: vi.fn(),
    register: vi.fn(),
    handleOAuthCallback: vi.fn(),
    logout: vi.fn(),
    refreshToken: vi.fn(),
    fetchProfile: vi.fn(),
    initialize: vi.fn(),
    clearError: vi.fn(),
  };
  return {
    useAuthStore: vi.fn((selector) => {
      if (typeof selector === 'function') return selector(store);
      return store;
    }),
  };
});

import LoginPage from '../login/page';

const mockedUseAuthStore = vi.mocked(useAuthStore);

describe('LoginPage', () => {
  let mockStore: {
    user: null;
    isAuthenticated: boolean;
    isInitialized: boolean;
    isLoading: boolean;
    error: string | null;
    login: ReturnType<typeof vi.fn>;
    register: ReturnType<typeof vi.fn>;
    handleOAuthCallback: ReturnType<typeof vi.fn>;
    logout: ReturnType<typeof vi.fn>;
    refreshToken: ReturnType<typeof vi.fn>;
    fetchProfile: ReturnType<typeof vi.fn>;
    initialize: ReturnType<typeof vi.fn>;
    clearError: ReturnType<typeof vi.fn>;
  };

  beforeEach(() => {
    vi.clearAllMocks();
    mockStore = {
      user: null,
      isAuthenticated: false,
      isInitialized: false,
      isLoading: false,
      error: null,
      login: vi.fn(),
      register: vi.fn(),
      handleOAuthCallback: vi.fn(),
      logout: vi.fn(),
      refreshToken: vi.fn(),
      fetchProfile: vi.fn(),
      initialize: vi.fn(),
      clearError: vi.fn(),
    };
    mockedUseAuthStore.mockImplementation((selector) => {
      if (typeof selector === 'function') return (selector as (s: typeof mockStore) => unknown)(mockStore);
      return mockStore as ReturnType<typeof useAuthStore>;
    });
  });

  it('renders login form with phone and password fields', () => {
    render(<LoginPage />);

    expect(screen.getByRole('heading', { name: 'Đăng nhập' })).toBeInTheDocument();
    expect(screen.getByLabelText('Số điện thoại')).toBeInTheDocument();
    expect(screen.getByLabelText('Mật khẩu')).toBeInTheDocument();
    expect(screen.getByRole('button', { name: /đăng nhập/i })).toBeInTheDocument();
  });

  it('renders OAuth buttons', () => {
    render(<LoginPage />);

    expect(screen.getByRole('button', { name: /google/i })).toBeInTheDocument();
    expect(screen.getByRole('button', { name: /zalo/i })).toBeInTheDocument();
  });

  it('renders register link', () => {
    render(<LoginPage />);

    const registerLink = screen.getByRole('link', { name: /đăng ký/i });
    expect(registerLink).toHaveAttribute('href', '/register');
  });

  it('submits form with valid data', async () => {
    mockStore.login.mockResolvedValue(undefined);
    render(<LoginPage />);

    await userEvent.type(screen.getByLabelText('Số điện thoại'), '0912345678');
    await userEvent.type(screen.getByLabelText('Mật khẩu'), 'password123');
    await userEvent.click(screen.getByRole('button', { name: /đăng nhập/i }));

    await waitFor(() => {
      expect(mockStore.login).toHaveBeenCalledWith({
        phone: '0912345678',
        password: 'password123',
      });
    });
  });

  it('shows validation errors for empty fields', async () => {
    render(<LoginPage />);

    await userEvent.click(screen.getByRole('button', { name: /đăng nhập/i }));

    await waitFor(() => {
      const alerts = screen.getAllByRole('alert');
      expect(alerts.length).toBeGreaterThan(0);
    });
  });

  it('toggles password visibility', async () => {
    render(<LoginPage />);

    const passwordInput = screen.getByLabelText('Mật khẩu');
    expect(passwordInput).toHaveAttribute('type', 'password');

    await userEvent.click(screen.getByText('Hiện'));
    expect(passwordInput).toHaveAttribute('type', 'text');

    await userEvent.click(screen.getByText('Ẩn'));
    expect(passwordInput).toHaveAttribute('type', 'password');
  });

  it('displays store error message', () => {
    mockStore.error = 'Sai mật khẩu';
    render(<LoginPage />);

    expect(screen.getByText('Sai mật khẩu')).toBeInTheDocument();
  });

  it('navigates to home after successful login', async () => {
    mockStore.login.mockResolvedValue(undefined);
    render(<LoginPage />);

    await userEvent.type(screen.getByLabelText('Số điện thoại'), '0912345678');
    await userEvent.type(screen.getByLabelText('Mật khẩu'), 'password123');
    await userEvent.click(screen.getByRole('button', { name: /đăng nhập/i }));

    await waitFor(() => {
      expect(mockPush).toHaveBeenCalledWith('/');
    });
  });
});
