/**
 * Comprehensive tests for PlatformUsers component
 *
 * Tests cover:
 * - Component rendering
 * - Loading states
 * - Error states
 * - User filtering and search
 * - Role filtering
 * - Masquerade functionality
 * - Email verification
 * - User editing
 */

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

// Mock react-i18next
vi.mock('react-i18next', () => ({
  useTranslation: () => ({
    t: (key: string) => key,
  }),
}));

// Mock hooks
const mockPlatformUsers = vi.fn();

vi.mock('../../../hooks/usePlatform', () => ({
  usePlatformUsers: () => mockPlatformUsers(),
}));

// Mock API functions
const mockVerifyUserEmail = vi.fn();

vi.mock('../../../api/platform', () => ({
  verifyUserEmail: (id: number) => mockVerifyUserEmail(id),
  PlatformUser: {},
}));

// Mock components
vi.mock('../components/PlatformListing', () => ({
  default: ({ title, description, data, renderRow, searchTerm, onSearchChange, filterValue, onFilterChange }: any) => (
    <div data-testid="platform-listing">
      <h1>{title}</h1>
      <p>{description}</p>
      <input
        placeholder="Search"
        value={searchTerm}
        onChange={(e) => onSearchChange(e.target.value)}
      />
      <select value={filterValue} onChange={(e) => onFilterChange(e.target.value)}>
        <option value="all">All Roles</option>
        <option value="superuser">Superuser</option>
        <option value="platform_manager">Platform Manager</option>
        <option value="platform_support">Platform Support</option>
      </select>
      <div data-testid="user-list">
        {data.map((user: any) => (
          <div key={user.id}>{renderRow(user)}</div>
        ))}
      </div>
    </div>
  ),
}));

vi.mock('../components/PlatformListRow', () => ({
  default: ({ primaryText, secondaryText, tertiaryText, actions }: any) => (
    <div data-testid="platform-list-row">
      <div>{primaryText}</div>
      {secondaryText && <div>{secondaryText}</div>}
      <div>{tertiaryText}</div>
      <div>{actions}</div>
    </div>
  ),
}));

vi.mock('../components/EditPlatformEntityModal', () => ({
  default: ({ entity, isOpen, onClose }: any) =>
    isOpen ? (
      <div data-testid="edit-modal">
        <div>Edit User: {entity?.username}</div>
        <button onClick={onClose}>Close</button>
      </div>
    ) : null,
}));

vi.mock('../../../components/ConfirmationModal', () => ({
  default: ({ isOpen, onClose, onConfirm, title, isLoading }: any) =>
    isOpen ? (
      <div data-testid="confirmation-modal">
        <div>{title}</div>
        <button onClick={onConfirm} disabled={isLoading}>
          Confirm
        </button>
        <button onClick={onClose}>Cancel</button>
      </div>
    ) : null,
}));

// Test data
const mockSuperuser = {
  id: 1,
  username: 'admin',
  email: 'admin@example.com',
  name: 'Admin User',
  full_name: 'Admin User',
  role: 'superuser',
  is_superuser: true,
  email_verified: true,
  business_name: null,
};

const mockPlatformManager = {
  id: 2,
  username: 'manager1',
  email: 'manager1@example.com',
  name: 'Platform Manager',
  full_name: 'Platform Manager',
  role: 'platform_manager',
  is_superuser: false,
  email_verified: true,
  business_name: null,
};

const mockPlatformSupport = {
  id: 3,
  username: 'support1',
  email: 'support1@example.com',
  name: 'Support Staff',
  full_name: 'Support Staff',
  role: 'platform_support',
  is_superuser: false,
  email_verified: false,
  business_name: null,
};

const mockBusinessOwner = {
  id: 4,
  username: 'owner1',
  email: 'owner1@example.com',
  name: 'Business Owner',
  full_name: 'Business Owner',
  role: 'owner',
  is_superuser: false,
  email_verified: true,
  business_name: 'Test Business',
};

// Test wrapper
const createWrapper = () => {
  const queryClient = new QueryClient({
    defaultOptions: {
      queries: { retry: false },
    },
  });

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

describe('PlatformUsers', () => {
  const mockOnMasquerade = vi.fn();

  beforeEach(() => {
    vi.clearAllMocks();
  });

  describe('Loading State', () => {
    it('should show loading state while fetching data', () => {
      mockPlatformUsers.mockReturnValue({
        data: undefined,
        isLoading: true,
        error: null,
      });

      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      expect(screen.getByTestId('platform-listing')).toBeInTheDocument();
    });
  });

  describe('Error State', () => {
    it('should display error when data fetch fails', () => {
      mockPlatformUsers.mockReturnValue({
        data: undefined,
        isLoading: false,
        error: new Error('Failed to load'),
      });

      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      expect(screen.getByTestId('platform-listing')).toBeInTheDocument();
    });
  });

  describe('Component Rendering', () => {
    beforeEach(() => {
      mockPlatformUsers.mockReturnValue({
        data: [mockSuperuser, mockPlatformManager, mockPlatformSupport, mockBusinessOwner],
        isLoading: false,
        error: null,
      });
    });

    it('should render the page title', () => {
      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      expect(screen.getByText('platform.userDirectory')).toBeInTheDocument();
    });

    it('should render the page description', () => {
      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      expect(screen.getByText('platform.userDirectoryDescription')).toBeInTheDocument();
    });

    it('should render search input', () => {
      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      expect(screen.getByPlaceholderText('Search')).toBeInTheDocument();
    });

    it('should render role filter dropdown', () => {
      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      expect(screen.getByRole('combobox')).toBeInTheDocument();
    });
  });

  describe('User Filtering', () => {
    beforeEach(() => {
      mockPlatformUsers.mockReturnValue({
        data: [mockSuperuser, mockPlatformManager, mockPlatformSupport, mockBusinessOwner],
        isLoading: false,
        error: null,
      });
    });

    it('should only show platform users', () => {
      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      // Should show platform users by their unique data (emails)
      expect(screen.getByText('admin@example.com')).toBeInTheDocument();
      expect(screen.getByText('manager1@example.com')).toBeInTheDocument();
      expect(screen.getByText('support1@example.com')).toBeInTheDocument();

      // Should not show business owner email
      expect(screen.queryByText('owner1@example.com')).not.toBeInTheDocument();
    });

    it('should filter users by role', async () => {
      const user = userEvent.setup();
      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      const roleFilter = screen.getByRole('combobox');
      await user.selectOptions(roleFilter, 'platform_manager');

      await waitFor(() => {
        // Should only show platform manager (check by unique email)
        expect(screen.getByText('manager1@example.com')).toBeInTheDocument();
        expect(screen.queryByText('admin@example.com')).not.toBeInTheDocument();
        expect(screen.queryByText('support1@example.com')).not.toBeInTheDocument();
      });
    });

    it('should show all platform users when "all" is selected', async () => {
      const user = userEvent.setup();
      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      const roleFilter = screen.getByRole('combobox');
      await user.selectOptions(roleFilter, 'platform_manager');
      await user.selectOptions(roleFilter, 'all');

      await waitFor(() => {
        expect(screen.getByText('admin@example.com')).toBeInTheDocument();
        expect(screen.getByText('manager1@example.com')).toBeInTheDocument();
        expect(screen.getByText('support1@example.com')).toBeInTheDocument();
      });
    });
  });

  describe('Search Functionality', () => {
    beforeEach(() => {
      mockPlatformUsers.mockReturnValue({
        data: [mockSuperuser, mockPlatformManager, mockPlatformSupport],
        isLoading: false,
        error: null,
      });
    });

    it('should filter users by name', async () => {
      const user = userEvent.setup();
      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      const searchInput = screen.getByPlaceholderText('Search');
      await user.type(searchInput, 'Admin');

      await waitFor(() => {
        expect(screen.getByText('admin@example.com')).toBeInTheDocument();
        expect(screen.queryByText('manager1@example.com')).not.toBeInTheDocument();
        expect(screen.queryByText('support1@example.com')).not.toBeInTheDocument();
      });
    });

    it('should filter users by email', async () => {
      const user = userEvent.setup();
      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      const searchInput = screen.getByPlaceholderText('Search');
      await user.type(searchInput, 'support1@');

      await waitFor(() => {
        expect(screen.queryByText('admin@example.com')).not.toBeInTheDocument();
        expect(screen.queryByText('manager1@example.com')).not.toBeInTheDocument();
        expect(screen.getByText('support1@example.com')).toBeInTheDocument();
      });
    });

    it('should filter users by username', async () => {
      const user = userEvent.setup();
      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      const searchInput = screen.getByPlaceholderText('Search');
      await user.type(searchInput, 'manager1');

      await waitFor(() => {
        expect(screen.queryByText('admin@example.com')).not.toBeInTheDocument();
        expect(screen.getByText('manager1@example.com')).toBeInTheDocument();
        expect(screen.queryByText('support1@example.com')).not.toBeInTheDocument();
      });
    });

    it('should be case-insensitive', async () => {
      const user = userEvent.setup();
      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      const searchInput = screen.getByPlaceholderText('Search');
      await user.type(searchInput, 'ADMIN');

      await waitFor(() => {
        expect(screen.getByText('Admin User')).toBeInTheDocument();
      });
    });
  });

  describe('Email Verification', () => {
    beforeEach(() => {
      mockPlatformUsers.mockReturnValue({
        data: [mockPlatformSupport],
        isLoading: false,
        error: null,
      });
    });

    it('should show verify button for unverified emails', () => {
      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      const verifyButtons = screen.getAllByText('platform.verify');
      expect(verifyButtons.length).toBeGreaterThan(0);
    });

    it('should not show verify button for verified emails', () => {
      mockPlatformUsers.mockReturnValue({
        data: [mockSuperuser],
        isLoading: false,
        error: null,
      });

      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      expect(screen.queryByText('platform.verify')).not.toBeInTheDocument();
    });

    it('should open confirmation modal when clicking verify button', async () => {
      const user = userEvent.setup();
      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      const verifyButton = screen.getByText('platform.verify');
      await user.click(verifyButton);

      await waitFor(() => {
        expect(screen.getByTestId('confirmation-modal')).toBeInTheDocument();
        expect(screen.getByText('platform.verifyEmail')).toBeInTheDocument();
      });
    });

    it('should call verifyUserEmail API when confirming verification', async () => {
      const user = userEvent.setup();
      mockVerifyUserEmail.mockResolvedValue({});

      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      const verifyButton = screen.getByText('platform.verify');
      await user.click(verifyButton);

      await waitFor(() => {
        expect(screen.getByTestId('confirmation-modal')).toBeInTheDocument();
      });

      const confirmButton = screen.getByText('Confirm');
      await user.click(confirmButton);

      await waitFor(() => {
        expect(mockVerifyUserEmail).toHaveBeenCalledWith(mockPlatformSupport.id);
      });
    });

    it('should close modal after successful verification', async () => {
      const user = userEvent.setup();
      mockVerifyUserEmail.mockResolvedValue({});

      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      const verifyButton = screen.getByText('platform.verify');
      await user.click(verifyButton);

      const confirmButton = screen.getByText('Confirm');
      await user.click(confirmButton);

      await waitFor(() => {
        expect(screen.queryByTestId('confirmation-modal')).not.toBeInTheDocument();
      });
    });
  });

  describe('Masquerade Functionality', () => {
    beforeEach(() => {
      mockPlatformUsers.mockReturnValue({
        data: [mockPlatformManager],
        isLoading: false,
        error: null,
      });
    });

    it('should show masquerade button for each user', () => {
      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      expect(screen.getByText('platform.masquerade')).toBeInTheDocument();
    });

    it('should call onMasquerade with user data when clicking masquerade button', async () => {
      const user = userEvent.setup();
      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      const masqueradeButton = screen.getByText('platform.masquerade');
      await user.click(masqueradeButton);

      expect(mockOnMasquerade).toHaveBeenCalledWith({
        id: mockPlatformManager.id,
        username: mockPlatformManager.username,
        name: mockPlatformManager.full_name,
        email: mockPlatformManager.email,
        role: mockPlatformManager.role,
      });
    });

    it('should disable masquerade button for superusers', () => {
      mockPlatformUsers.mockReturnValue({
        data: [mockSuperuser],
        isLoading: false,
        error: null,
      });

      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      const masqueradeButton = screen.getByText('platform.masquerade');
      expect(masqueradeButton).toBeDisabled();
    });
  });

  describe('Edit Functionality', () => {
    beforeEach(() => {
      mockPlatformUsers.mockReturnValue({
        data: [mockPlatformManager],
        isLoading: false,
        error: null,
      });
    });

    it('should show edit button for each user', () => {
      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      expect(screen.getByText('common.edit')).toBeInTheDocument();
    });

    it('should open edit modal when clicking edit button', async () => {
      const user = userEvent.setup();
      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

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

      await waitFor(() => {
        expect(screen.getByTestId('edit-modal')).toBeInTheDocument();
        expect(screen.getByText('Edit User: manager1')).toBeInTheDocument();
      });
    });

    it('should close edit modal when clicking close button', async () => {
      const user = userEvent.setup();
      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

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

      await waitFor(() => {
        expect(screen.getByTestId('edit-modal')).toBeInTheDocument();
      });

      const closeButton = screen.getByText('Close');
      await user.click(closeButton);

      await waitFor(() => {
        expect(screen.queryByTestId('edit-modal')).not.toBeInTheDocument();
      });
    });
  });

  describe('Combined Filtering', () => {
    beforeEach(() => {
      mockPlatformUsers.mockReturnValue({
        data: [mockSuperuser, mockPlatformManager, mockPlatformSupport],
        isLoading: false,
        error: null,
      });
    });

    it('should apply both search and role filter', async () => {
      const user = userEvent.setup();
      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      // Apply role filter
      const roleFilter = screen.getByRole('combobox');
      await user.selectOptions(roleFilter, 'platform_manager');

      // Apply search
      const searchInput = screen.getByPlaceholderText('Search');
      await user.type(searchInput, 'manager');

      await waitFor(() => {
        expect(screen.getByText('manager1@example.com')).toBeInTheDocument();
        expect(screen.queryByText('admin@example.com')).not.toBeInTheDocument();
        expect(screen.queryByText('support1@example.com')).not.toBeInTheDocument();
      });
    });
  });

  describe('Empty State', () => {
    it('should handle empty user list', () => {
      mockPlatformUsers.mockReturnValue({
        data: [],
        isLoading: false,
        error: null,
      });

      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      const userList = screen.getByTestId('user-list');
      expect(userList).toBeEmptyDOMElement();
    });

    it('should handle search with no results', async () => {
      const user = userEvent.setup();
      mockPlatformUsers.mockReturnValue({
        data: [mockPlatformManager],
        isLoading: false,
        error: null,
      });

      render(<PlatformUsers onMasquerade={mockOnMasquerade} />, { wrapper: createWrapper() });

      const searchInput = screen.getByPlaceholderText('Search');
      await user.type(searchInput, 'nonexistent');

      await waitFor(() => {
        const userList = screen.getByTestId('user-list');
        expect(userList).toBeEmptyDOMElement();
      });
    });
  });
});
