import { render, screen, waitFor } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import userEvent from '@testing-library/user-event';
import { BrowserRouter } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ProfileForm } from './ProfileForm';

// Mock useTranslation
vi.mock('@/hooks/useTranslation', () => ({
  useTranslation: () => ({
    t: (key: string) => key,
    i18n: { changeLanguage: vi.fn() },
    language: 'fr',
    changeLanguage: vi.fn(),
    isReady: true,
  }),
}));

// Mock useAuthStore
const mockUser = {
  id: 1,
  username: 'testuser',
  email: 'test@example.com',
  first_name: 'Test',
  last_name: 'User',
  bio: 'Test bio',
};

const mockRefreshUser = vi.fn();

vi.mock('@/stores/auth', () => ({
  useAuthStore: () => ({
    user: mockUser,
    refreshUser: mockRefreshUser,
    isAuthenticated: true,
  }),
}));

// Mock useUIStore
vi.mock('@/stores/ui', () => ({
  useUIStore: () => ({
    addNotification: vi.fn(),
  }),
}));

// Mock apiClient
vi.mock('@/services/api/client', () => ({
  apiClient: {
    put: vi.fn().mockResolvedValue({
      data: {
        id: 1,
        username: 'testuser',
        email: 'test@example.com',
        first_name: 'Test',
        last_name: 'User',
        bio: 'Test bio',
      },
    }),
  },
}));

const createTestQueryClient = () =>
  new QueryClient({
    defaultOptions: {
      queries: { retry: false },
      mutations: { retry: false },
    },
  });

const TestWrapper = ({ children }: { children: React.ReactNode }) => {
  const queryClient = createTestQueryClient();
  return (
    <QueryClientProvider client={queryClient}>
      <BrowserRouter>{children}</BrowserRouter>
    </QueryClientProvider>
  );
};

describe('ProfileForm Component', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('renders profile form correctly', () => {
    render(
      <TestWrapper>
        <ProfileForm />
      </TestWrapper>,
    );

    expect(screen.getByText('profile.title')).toBeInTheDocument();
    expect(screen.getByText('profile.personalInfo')).toBeInTheDocument();
  });

  it('displays user information', () => {
    render(
      <TestWrapper>
        <ProfileForm />
      </TestWrapper>,
    );

    expect(screen.getByDisplayValue('testuser')).toBeInTheDocument();
    expect(screen.getByDisplayValue('test@example.com')).toBeInTheDocument();
    expect(screen.getByDisplayValue('Test')).toBeInTheDocument();
    expect(screen.getByDisplayValue('User')).toBeInTheDocument();
  });

  it('enables editing mode when edit button is clicked', async () => {
    const user = userEvent.setup();
    render(
      <TestWrapper>
        <ProfileForm />
      </TestWrapper>,
    );

    const editButton = screen.getByText('profile.edit');
    await user.click(editButton);

    // Les champs devraient être éditables
    const usernameInput = screen.getByDisplayValue('testuser');
    expect(usernameInput).not.toBeDisabled();
  });

  it('validates form fields', async () => {
    const user = userEvent.setup();
    render(
      <TestWrapper>
        <ProfileForm />
      </TestWrapper>,
    );

    const editButton = screen.getByText('profile.edit');
    await user.click(editButton);

    // Vider le champ username
    const usernameInput = screen.getByDisplayValue('testuser');
    await user.clear(usernameInput);
    await user.type(usernameInput, 'ab'); // Trop court

    // Vider le champ email
    const emailInput = screen.getByDisplayValue('test@example.com');
    await user.clear(emailInput);
    await user.type(emailInput, 'invalid-email');

    // Soumettre le formulaire
    const saveButton = screen.getByText('profile.save');
    await user.click(saveButton);

    // Attendre que les erreurs de validation apparaissent
    await waitFor(() => {
      expect(
        screen.getByText(
          /Le nom d'utilisateur doit contenir au moins 3 caractères/,
        ),
      ).toBeInTheDocument();
    });
  });

  it('allows form submission with valid data', async () => {
    const user = userEvent.setup();
    render(
      <TestWrapper>
        <ProfileForm />
      </TestWrapper>,
    );

    const editButton = screen.getByText('profile.edit');
    await user.click(editButton);

    const usernameInput = screen.getByDisplayValue('testuser');
    expect(usernameInput).not.toBeDisabled();

    await user.clear(usernameInput);
    await user.type(usernameInput, 'newusername');

    const saveButton = screen.getByText('profile.save');
    expect(saveButton).toBeInTheDocument();
    expect(saveButton).not.toBeDisabled();
  });

  it('cancels editing and resets form', async () => {
    const user = userEvent.setup();
    render(
      <TestWrapper>
        <ProfileForm />
      </TestWrapper>,
    );

    const editButton = screen.getByText('profile.edit');
    await user.click(editButton);

    const usernameInput = screen.getByDisplayValue('testuser');
    await user.clear(usernameInput);
    await user.type(usernameInput, 'modified');

    const cancelButton = screen.getByText('profile.cancel');
    await user.click(cancelButton);

    // Le formulaire devrait être réinitialisé
    await waitFor(() => {
      expect(screen.getByDisplayValue('testuser')).toBeInTheDocument();
    });

    // Les champs devraient être désactivés
    expect(usernameInput).toBeDisabled();
  });

  it('handles avatar upload', async () => {
    const user = userEvent.setup();
    render(
      <TestWrapper>
        <ProfileForm />
      </TestWrapper>,
    );

    const editButton = screen.getByText('profile.edit');
    await user.click(editButton);

    // Trouver le bouton d'upload d'avatar
    const avatarButton = screen.getByText('profile.avatar.changePhoto');
    expect(avatarButton).toBeInTheDocument();
  });
});
