/**
 * AdminUsersTable Component Tests
 * 
 * Tests for the AdminUsersTable component that displays users in a table
 * with selection, status management, and deletion capabilities.
 */

import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import { AdminUsersTable } from './AdminUsersTable';
import { describe, it, expect, vi } from 'vitest';

// Mock the DateDisplay component
vi.mock('@/lib/display-objects/DateDisplay', () => ({
  DateDisplay: {
    formatShort: (date: string) => new Date(date).toLocaleDateString(),
  },
}));

// Mock the AdminUsersViewData
vi.mock('@/lib/view-data/AdminUsersViewData', () => ({
  AdminUsersViewData: {},
}));

// Mock the Button component
vi.mock('@/ui/Button', () => ({
  Button: ({ children, onClick, disabled }: any) => (
    <button onClick={onClick} disabled={disabled} data-testid="button">
      {children}
    </button>
  ),
}));

// Mock the IconButton component
vi.mock('@/ui/IconButton', () => ({
  IconButton: ({ onClick, disabled, icon, title }: any) => (
    <button onClick={onClick} disabled={disabled} data-testid="icon-button" title={title}>
      {title}
    </button>
  ),
}));

// Mock the SimpleCheckbox component
vi.mock('@/ui/SimpleCheckbox', () => ({
  SimpleCheckbox: ({ checked, onChange, 'aria-label': ariaLabel }: any) => (
    <input
      type="checkbox"
      checked={checked}
      onChange={onChange}
      aria-label={ariaLabel}
      data-testid="checkbox"
    />
  ),
}));

// Mock the Badge component
vi.mock('@/ui/Badge', () => ({
  Badge: ({ children }: any) => <span data-testid="badge">{children}</span>,
}));

// Mock the Box component
vi.mock('@/ui/Box', () => ({
  Box: ({ children }: any) => <div>{children}</div>,
}));

// Mock the Group component
vi.mock('@/ui/Group', () => ({
  Group: ({ children }: any) => <div>{children}</div>,
}));

// Mock the DriverIdentity component
vi.mock('@/ui/DriverIdentity', () => ({
  DriverIdentity: ({ driver, meta }: any) => (
    <div data-testid="driver-identity">
      <span>{driver.name}</span>
      <span>{meta}</span>
    </div>
  ),
}));

// Mock the Table components
vi.mock('@/ui/Table', () => ({
  Table: ({ children }: any) => <table>{children}</table>,
  TableHead: ({ children }: any) => <thead>{children}</thead>,
  TableBody: ({ children }: any) => <tbody>{children}</tbody>,
  TableHeader: ({ children, w, textAlign }: any) => <th style={{ width: w, textAlign }}>{children}</th>,
  TableRow: ({ children, variant }: any) => <tr data-variant={variant}>{children}</tr>,
  TableCell: ({ children }: any) => <td>{children}</td>,
}));

// Mock the Text component
vi.mock('@/ui/Text', () => ({
  Text: ({ children, size, variant }: any) => (
    <span data-size={size} data-variant={variant}>{children}</span>
  ),
}));

// Mock the UserStatusTag component
vi.mock('./UserStatusTag', () => ({
  UserStatusTag: ({ status }: any) => <span data-testid="status-tag">{status}</span>,
}));

describe('AdminUsersTable', () => {
  const mockUsers = [
    {
      id: '1',
      displayName: 'John Doe',
      email: 'john@example.com',
      roles: ['admin'],
      status: 'active',
      lastLoginAt: '2024-01-15T10:30:00Z',
    },
    {
      id: '2',
      displayName: 'Jane Smith',
      email: 'jane@example.com',
      roles: ['user'],
      status: 'suspended',
      lastLoginAt: '2024-01-14T15:45:00Z',
    },
    {
      id: '3',
      displayName: 'Bob Johnson',
      email: 'bob@example.com',
      roles: ['user'],
      status: 'active',
      lastLoginAt: null,
    },
  ];

  const defaultProps = {
    users: mockUsers,
    selectedUserIds: [],
    onSelectUser: vi.fn(),
    onSelectAll: vi.fn(),
    onUpdateStatus: vi.fn(),
    onDeleteUser: vi.fn(),
    deletingUserId: null,
  };

  it('should render table headers', () => {
    render(<AdminUsersTable {...defaultProps} />);

    expect(screen.getByText('User')).toBeTruthy();
    expect(screen.getByText('Roles')).toBeTruthy();
    expect(screen.getByText('Status')).toBeTruthy();
    expect(screen.getByText('Last Login')).toBeTruthy();
    expect(screen.getByText('Actions')).toBeTruthy();
  });

  it('should render user rows', () => {
    render(<AdminUsersTable {...defaultProps} />);

    expect(screen.getByText('John Doe')).toBeTruthy();
    expect(screen.getByText('john@example.com')).toBeTruthy();
    expect(screen.getByText('Jane Smith')).toBeTruthy();
    expect(screen.getByText('jane@example.com')).toBeTruthy();
    expect(screen.getByText('Bob Johnson')).toBeTruthy();
    expect(screen.getByText('bob@example.com')).toBeTruthy();
  });

  it('should render user roles', () => {
    render(<AdminUsersTable {...defaultProps} />);

    expect(screen.getByText('admin')).toBeTruthy();
    expect(screen.getByText('user')).toBeTruthy();
  });

  it('should render user status tags', () => {
    render(<AdminUsersTable {...defaultProps} />);

    expect(screen.getAllByTestId('status-tag')).toHaveLength(3);
  });

  it('should render last login dates', () => {
    render(<AdminUsersTable {...defaultProps} />);

    expect(screen.getByText('1/15/2024')).toBeTruthy();
    expect(screen.getByText('1/14/2024')).toBeTruthy();
    expect(screen.getByText('Never')).toBeTruthy();
  });

  it('should render select all checkbox', () => {
    render(<AdminUsersTable {...defaultProps} />);

    expect(screen.getByLabelText('Select all users')).toBeTruthy();
  });

  it('should render individual user checkboxes', () => {
    render(<AdminUsersTable {...defaultProps} />);

    expect(screen.getByLabelText('Select user John Doe')).toBeTruthy();
    expect(screen.getByLabelText('Select user Jane Smith')).toBeTruthy();
    expect(screen.getByLabelText('Select user Bob Johnson')).toBeTruthy();
  });

  it('should render suspend button for active users', () => {
    render(<AdminUsersTable {...defaultProps} />);

    expect(screen.getByText('Suspend')).toBeTruthy();
  });

  it('should render activate button for suspended users', () => {
    render(<AdminUsersTable {...defaultProps} />);

    expect(screen.getByText('Activate')).toBeTruthy();
  });

  it('should render delete button for all users', () => {
    render(<AdminUsersTable {...defaultProps} />);

    expect(screen.getAllByTitle('Delete')).toHaveLength(3);
  });

  it('should render more button for all users', () => {
    render(<AdminUsersTable {...defaultProps} />);

    expect(screen.getAllByTitle('More')).toHaveLength(3);
  });

  it('should highlight selected rows', () => {
    const props = {
      ...defaultProps,
      selectedUserIds: ['1', '3'],
    };

    render(<AdminUsersTable {...props} />);

    // Check that selected rows have highlight variant
    const rows = screen.getAllByRole('row');
    expect(rows[1]).toHaveAttribute('data-variant', 'highlight');
    expect(rows[3]).toHaveAttribute('data-variant', 'highlight');
  });

  it('should disable delete button when deleting', () => {
    const props = {
      ...defaultProps,
      deletingUserId: '1',
    };

    render(<AdminUsersTable {...props} />);

    const deleteButtons = screen.getAllByTitle('Delete');
    expect(deleteButtons[0]).toBeDisabled();
  });

  it('should call onSelectUser when checkbox is clicked', () => {
    const onSelectUser = vi.fn();
    const props = {
      ...defaultProps,
      onSelectUser,
    };

    render(<AdminUsersTable {...props} />);

    const checkboxes = screen.getAllByTestId('checkbox');
    fireEvent.click(checkboxes[1]); // Click first user checkbox

    expect(onSelectUser).toHaveBeenCalledWith('1');
  });

  it('should call onSelectAll when select all checkbox is clicked', () => {
    const onSelectAll = vi.fn();
    const props = {
      ...defaultProps,
      onSelectAll,
    };

    render(<AdminUsersTable {...props} />);

    const selectAllCheckbox = screen.getByLabelText('Select all users');
    fireEvent.click(selectAllCheckbox);

    expect(onSelectAll).toHaveBeenCalled();
  });

  it('should call onUpdateStatus when suspend button is clicked', () => {
    const onUpdateStatus = vi.fn();
    const props = {
      ...defaultProps,
      onUpdateStatus,
    };

    render(<AdminUsersTable {...props} />);

    const suspendButtons = screen.getAllByText('Suspend');
    fireEvent.click(suspendButtons[0]);

    expect(onUpdateStatus).toHaveBeenCalledWith('1', 'suspended');
  });

  it('should call onUpdateStatus when activate button is clicked', () => {
    const onUpdateStatus = vi.fn();
    const props = {
      ...defaultProps,
      onUpdateStatus,
    };

    render(<AdminUsersTable {...props} />);

    const activateButtons = screen.getAllByText('Activate');
    fireEvent.click(activateButtons[0]);

    expect(onUpdateStatus).toHaveBeenCalledWith('2', 'active');
  });

  it('should call onDeleteUser when delete button is clicked', () => {
    const onDeleteUser = vi.fn();
    const props = {
      ...defaultProps,
      onDeleteUser,
    };

    render(<AdminUsersTable {...props} />);

    const deleteButtons = screen.getAllByTitle('Delete');
    fireEvent.click(deleteButtons[0]);

    expect(onDeleteUser).toHaveBeenCalledWith('1');
  });

  it('should render empty table when no users', () => {
    const props = {
      ...defaultProps,
      users: [],
    };

    render(<AdminUsersTable {...props} />);

    // Should render table headers but no rows
    expect(screen.getByText('User')).toBeTruthy();
    expect(screen.getByText('Roles')).toBeTruthy();
    expect(screen.getByText('Status')).toBeTruthy();
    expect(screen.getByText('Last Login')).toBeTruthy();
    expect(screen.getByText('Actions')).toBeTruthy();
  });

  it('should render with all users selected', () => {
    const props = {
      ...defaultProps,
      selectedUserIds: ['1', '2', '3'],
    };

    render(<AdminUsersTable {...props} />);

    const selectAllCheckbox = screen.getByLabelText('Select all users');
    expect(selectAllCheckbox).toBeChecked();
  });

  it('should render with some users selected', () => {
    const props = {
      ...defaultProps,
      selectedUserIds: ['1', '2'],
    };

    render(<AdminUsersTable {...props} />);

    const selectAllCheckbox = screen.getByLabelText('Select all users');
    expect(selectAllCheckbox).not.toBeChecked();
  });
});
