import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, waitFor, fireEvent } from '@/test/helpers';
import { BrowserRouter } from 'react-router-dom';
import { LoginForm } from './LoginForm';
import * as emailVerificationService from '../services/emailVerificationService';

// Mock useAuthStore
const mockLogin = vi.fn();
const mockClearError = vi.fn();
const mockError = { message: '', code: '' };

vi.mock('@/stores/auth', () => ({
  useAuthStore: () => ({
    login: mockLogin,
    isLoading: false,
    error: mockError,
    clearError: mockClearError,
  }),
}));

// Mock useTranslation
vi.mock('@/hooks/useTranslation', () => ({
  useTranslation: () => ({
    t: (key: string) => key,
  }),
}));

// Mock emailVerificationService
vi.mock('../services/emailVerificationService', () => ({
  resendVerificationEmail: vi.fn(),
}));

describe('LoginForm - Resend Verification Email', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    mockError.message = '';
    mockError.code = '';
  });

  describe('Resend verification email button', () => {
    it('should display resend button when error indicates email not verified', async () => {
      mockError.message = 'Email not verified';

      render(
        <BrowserRouter>
          <LoginForm />
        </BrowserRouter>,
      );

      await waitFor(() => {
        expect(screen.getByText(/email not verified/i)).toBeInTheDocument();
        expect(
          screen.getByText(/resend verification email/i),
        ).toBeInTheDocument();
      });
    });

    it('should not display resend button for other errors', async () => {
      mockError.message = 'Invalid credentials';

      render(
        <BrowserRouter>
          <LoginForm />
        </BrowserRouter>,
      );

      await waitFor(() => {
        expect(screen.getByText(/invalid credentials/i)).toBeInTheDocument();
        expect(
          screen.queryByText(/resend verification email/i),
        ).not.toBeInTheDocument();
      });
    });

    it('should call resendVerificationEmail when resend button is clicked', async () => {
      mockError.message = 'Email not verified';
      vi.mocked(
        emailVerificationService.resendVerificationEmail,
      ).mockResolvedValue({
        message: 'verification email sent',
      });

      render(
        <BrowserRouter>
          <LoginForm />
        </BrowserRouter>,
      );

      await waitFor(() => {
        expect(
          screen.getByText(/resend verification email/i),
        ).toBeInTheDocument();
      });

      const emailInput = screen.getByLabelText(/email/i);
      fireEvent.change(emailInput, { target: { value: 'test@example.com' } });

      const resendButton = screen.getByText(/resend verification email/i);
      fireEvent.click(resendButton);

      await waitFor(() => {
        expect(
          emailVerificationService.resendVerificationEmail,
        ).toHaveBeenCalledWith('test@example.com');
      });
    });

    it('should display cooldown countdown after resending email', async () => {
      mockError.message = 'Email not verified';
      vi.mocked(
        emailVerificationService.resendVerificationEmail,
      ).mockResolvedValue({
        message: 'verification email sent',
      });

      vi.useFakeTimers();
      render(
        <BrowserRouter>
          <LoginForm />
        </BrowserRouter>,
      );

      await waitFor(() => {
        expect(
          screen.getByText(/resend verification email/i),
        ).toBeInTheDocument();
      });

      const emailInput = screen.getByLabelText(/email/i);
      fireEvent.change(emailInput, { target: { value: 'test@example.com' } });

      const resendButton = screen.getByText(/resend verification email/i);
      fireEvent.click(resendButton);

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

      vi.useRealTimers();
    });

    it('should display confirmation message after successful resend', async () => {
      mockError.message = 'Email not verified';
      vi.mocked(
        emailVerificationService.resendVerificationEmail,
      ).mockResolvedValue({
        message: 'verification email sent',
      });

      render(
        <BrowserRouter>
          <LoginForm />
        </BrowserRouter>,
      );

      await waitFor(() => {
        expect(
          screen.getByText(/resend verification email/i),
        ).toBeInTheDocument();
      });

      const emailInput = screen.getByLabelText(/email/i);
      fireEvent.change(emailInput, { target: { value: 'test@example.com' } });

      const resendButton = screen.getByText(/resend verification email/i);
      fireEvent.click(resendButton);

      await waitFor(() => {
        expect(
          screen.getByText(/verification email sent/i),
        ).toBeInTheDocument();
      });
    });

    it('should display error message when resend fails', async () => {
      mockError.message = 'Email not verified';
      vi.mocked(
        emailVerificationService.resendVerificationEmail,
      ).mockRejectedValue({
        message: 'Failed to resend email',
        code: '500',
      });

      render(
        <BrowserRouter>
          <LoginForm />
        </BrowserRouter>,
      );

      await waitFor(() => {
        expect(
          screen.getByText(/resend verification email/i),
        ).toBeInTheDocument();
      });

      const emailInput = screen.getByLabelText(/email/i);
      fireEvent.change(emailInput, { target: { value: 'test@example.com' } });

      const resendButton = screen.getByText(/resend verification email/i);
      fireEvent.click(resendButton);

      await waitFor(() => {
        expect(screen.getByText(/failed to resend email/i)).toBeInTheDocument();
      });
    });
  });
});
