/**
 * Comprehensive tests for PlatformStaff component
 *
 * Tests cover:
 * - Component rendering
 * - Loading states
 * - Error states
 * - User filtering and search
 * - Staff member display
 * - Permission display
 * - Edit functionality
 * - Role-based access control
 */

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

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

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

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

vi.mock('../../../hooks/useAuth', () => ({
  useCurrentUser: () => mockCurrentUser(),
}));

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

// Test data
const mockSuperuser = {
  id: 1,
  username: 'admin',
  email: 'admin@example.com',
  full_name: 'Admin User',
  role: 'superuser',
  is_active: true,
  is_superuser: true,
  permissions: {},
  created_at: '2024-01-01T00:00:00Z',
  last_login: '2024-12-01T10:00:00Z',
};

const mockPlatformManager = {
  id: 2,
  username: 'manager1',
  email: 'manager1@example.com',
  full_name: 'Platform Manager',
  role: 'platform_manager',
  is_active: true,
  is_superuser: false,
  permissions: {
    can_approve_plugins: true,
    can_whitelist_urls: true,
  },
  created_at: '2024-02-01T00:00:00Z',
  last_login: '2024-12-05T14:30:00Z',
};

const mockPlatformSupport = {
  id: 3,
  username: 'support1',
  email: 'support1@example.com',
  full_name: 'Support Staff',
  role: 'platform_support',
  is_active: true,
  is_superuser: false,
  permissions: {},
  created_at: '2024-03-01T00:00:00Z',
  last_login: null,
};

const mockInactivePlatformManager = {
  id: 4,
  username: 'manager2',
  email: 'manager2@example.com',
  full_name: 'Inactive Manager',
  role: 'platform_manager',
  is_active: false,
  is_superuser: false,
  permissions: {
    can_approve_plugins: false,
  },
  created_at: '2024-04-01T00:00:00Z',
  last_login: '2024-11-01T09:00:00Z',
};

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

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

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

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

      render(<PlatformStaff />, { wrapper: createWrapper() });

      // Check for loading spinner by class name
      const spinner = document.querySelector('.animate-spin');
      expect(spinner).toBeInTheDocument();
    });
  });

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

      render(<PlatformStaff />, { wrapper: createWrapper() });

      expect(screen.getByText('Failed to load platform staff')).toBeInTheDocument();
    });
  });

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

    it('should render the page header', () => {
      render(<PlatformStaff />, { wrapper: createWrapper() });

      expect(screen.getByText('Platform Staff')).toBeInTheDocument();
      expect(screen.getByText('Manage platform managers and support staff')).toBeInTheDocument();
    });

    it('should render the add staff button', () => {
      render(<PlatformStaff />, { wrapper: createWrapper() });

      expect(screen.getByText('Add Staff Member')).toBeInTheDocument();
    });

    it('should render the search input', () => {
      render(<PlatformStaff />, { wrapper: createWrapper() });

      expect(screen.getByPlaceholderText('Search staff by name, email, or username...')).toBeInTheDocument();
    });

    it('should render stats cards', () => {
      render(<PlatformStaff />, { wrapper: createWrapper() });

      expect(screen.getByText('Total Staff')).toBeInTheDocument();
      expect(screen.getByText('Platform Managers')).toBeInTheDocument();
      const supportStaffElements = screen.getAllByText('Support Staff');
      // Should find at least one (the header label)
      expect(supportStaffElements.length).toBeGreaterThan(0);
    });
  });

  describe('Staff Filtering', () => {
    beforeEach(() => {
      mockCurrentUser.mockReturnValue({ data: mockSuperuser });
    });

    it('should filter out superusers from staff list', () => {
      mockPlatformUsers.mockReturnValue({
        data: [mockSuperuser, mockPlatformManager, mockPlatformSupport],
        isLoading: false,
        error: null,
      });

      render(<PlatformStaff />, { wrapper: createWrapper() });

      // Should not show superuser
      expect(screen.queryByText('admin@example.com')).not.toBeInTheDocument();
      // Should show platform staff
      expect(screen.getByText('manager1@example.com')).toBeInTheDocument();
      expect(screen.getByText('support1@example.com')).toBeInTheDocument();
    });

    it('should display correct staff counts', () => {
      mockPlatformUsers.mockReturnValue({
        data: [mockPlatformManager, mockPlatformSupport, mockInactivePlatformManager],
        isLoading: false,
        error: null,
      });

      render(<PlatformStaff />, { wrapper: createWrapper() });

      // Check that counts are displayed (they are in the stats section)
      expect(screen.getByText('Total Staff')).toBeInTheDocument();
      expect(screen.getByText('Platform Managers')).toBeInTheDocument();

      // Find cards by structure and verify counts
      const cards = screen.getAllByText(/Total Staff|Platform Managers|Support Staff/);
      expect(cards.length).toBeGreaterThan(0);
    });
  });

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

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

      const searchInput = screen.getByPlaceholderText('Search staff by name, email, or username...');
      await user.type(searchInput, 'Platform Manager');

      expect(screen.getByText('manager1@example.com')).toBeInTheDocument();
      expect(screen.queryByText('support1@example.com')).not.toBeInTheDocument();
    });

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

      const searchInput = screen.getByPlaceholderText('Search staff by name, email, or username...');
      await user.type(searchInput, 'support1@example');

      expect(screen.queryByText('manager1@example.com')).not.toBeInTheDocument();
      expect(screen.getByText('support1@example.com')).toBeInTheDocument();
    });

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

      const searchInput = screen.getByPlaceholderText('Search staff by name, email, or username...');
      await user.type(searchInput, 'manager1');

      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(<PlatformStaff />, { wrapper: createWrapper() });

      const searchInput = screen.getByPlaceholderText('Search staff by name, email, or username...');
      await user.type(searchInput, 'MANAGER');

      expect(screen.getByText('manager1@example.com')).toBeInTheDocument();
    });
  });

  describe('Staff Member Display', () => {
    beforeEach(() => {
      mockCurrentUser.mockReturnValue({ data: mockSuperuser });
      mockPlatformUsers.mockReturnValue({
        data: [mockPlatformManager, mockPlatformSupport, mockInactivePlatformManager],
        isLoading: false,
        error: null,
      });
    });

    it('should display staff member information', () => {
      render(<PlatformStaff />, { wrapper: createWrapper() });

      // Check for email which is unique
      expect(screen.getByText('manager1@example.com')).toBeInTheDocument();
      // Check for role badge (there may be multiple "Platform Manager" texts)
      const platformManagerElements = screen.getAllByText('Platform Manager');
      expect(platformManagerElements.length).toBeGreaterThan(0);
    });

    it('should display role badges', () => {
      render(<PlatformStaff />, { wrapper: createWrapper() });

      expect(screen.getAllByText('Platform Manager').length).toBeGreaterThan(0);
      expect(screen.getByText('Platform Support')).toBeInTheDocument();
    });

    it('should display active status', () => {
      render(<PlatformStaff />, { wrapper: createWrapper() });

      const activeStatuses = screen.getAllByText('Active');
      expect(activeStatuses.length).toBeGreaterThan(0);
    });

    it('should display inactive status', () => {
      render(<PlatformStaff />, { wrapper: createWrapper() });

      expect(screen.getByText('Inactive')).toBeInTheDocument();
    });

    it('should format last login date', () => {
      render(<PlatformStaff />, { wrapper: createWrapper() });

      // Should show formatted dates for users with last_login
      const table = screen.getByRole('table');
      expect(table).toBeInTheDocument();
    });

    it('should display "Never" for users without last login', () => {
      render(<PlatformStaff />, { wrapper: createWrapper() });

      expect(screen.getByText('Never')).toBeInTheDocument();
    });
  });

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

    it('should display plugin approver permission', () => {
      render(<PlatformStaff />, { wrapper: createWrapper() });

      expect(screen.getByText('Plugin Approver')).toBeInTheDocument();
    });

    it('should display URL whitelister permission', () => {
      render(<PlatformStaff />, { wrapper: createWrapper() });

      expect(screen.getByText('URL Whitelister')).toBeInTheDocument();
    });

    it('should display "No special permissions" for users without permissions', () => {
      render(<PlatformStaff />, { wrapper: createWrapper() });

      expect(screen.getByText('No special permissions')).toBeInTheDocument();
    });
  });

  describe('Edit Functionality', () => {
    it('should allow superuser to edit any staff member', async () => {
      const user = userEvent.setup();
      mockCurrentUser.mockReturnValue({ data: mockSuperuser });
      mockPlatformUsers.mockReturnValue({
        data: [mockPlatformManager, mockPlatformSupport],
        isLoading: false,
        error: null,
      });

      render(<PlatformStaff />, { wrapper: createWrapper() });

      const editButtons = screen.getAllByText('Edit');
      await user.click(editButtons[0]);

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

    it('should allow platform_manager to edit platform_support users', async () => {
      const user = userEvent.setup();
      mockCurrentUser.mockReturnValue({ data: mockPlatformManager });
      mockPlatformUsers.mockReturnValue({
        data: [mockPlatformSupport],
        isLoading: false,
        error: null,
      });

      render(<PlatformStaff />, { wrapper: createWrapper() });

      const editButton = screen.getByText('Edit');
      expect(editButton).not.toBeDisabled();
    });

    it('should not allow platform_manager to edit other platform_managers', async () => {
      const anotherManager = { ...mockPlatformManager, id: 5, username: 'manager3' };
      mockCurrentUser.mockReturnValue({ data: mockPlatformManager });
      mockPlatformUsers.mockReturnValue({
        data: [anotherManager],
        isLoading: false,
        error: null,
      });

      render(<PlatformStaff />, { wrapper: createWrapper() });

      const editButton = screen.getByText('Edit');
      expect(editButton).toBeDisabled();
    });

    it('should close modal when close button is clicked', async () => {
      const user = userEvent.setup();
      mockCurrentUser.mockReturnValue({ data: mockSuperuser });
      mockPlatformUsers.mockReturnValue({
        data: [mockPlatformManager],
        isLoading: false,
        error: null,
      });

      render(<PlatformStaff />, { wrapper: createWrapper() });

      const editButton = screen.getByText('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('Empty State', () => {
    it('should display empty state when no staff members exist', () => {
      mockCurrentUser.mockReturnValue({ data: mockSuperuser });
      mockPlatformUsers.mockReturnValue({
        data: [],
        isLoading: false,
        error: null,
      });

      render(<PlatformStaff />, { wrapper: createWrapper() });

      expect(screen.getByText('No staff members found')).toBeInTheDocument();
      expect(screen.getByText('Add your first platform staff member to get started')).toBeInTheDocument();
    });

    it('should display empty state with search message when search has no results', async () => {
      const user = userEvent.setup();
      mockCurrentUser.mockReturnValue({ data: mockSuperuser });
      mockPlatformUsers.mockReturnValue({
        data: [mockPlatformManager],
        isLoading: false,
        error: null,
      });

      render(<PlatformStaff />, { wrapper: createWrapper() });

      const searchInput = screen.getByPlaceholderText('Search staff by name, email, or username...');
      await user.type(searchInput, 'nonexistent');

      expect(screen.getByText('No staff members found')).toBeInTheDocument();
      expect(screen.getByText('Try adjusting your search criteria')).toBeInTheDocument();
    });
  });

  describe('User Interactions', () => {
    it('should show alert when clicking add staff member button', async () => {
      const user = userEvent.setup();
      const alertSpy = vi.spyOn(window, 'alert').mockImplementation(() => {});

      mockCurrentUser.mockReturnValue({ data: mockSuperuser });
      mockPlatformUsers.mockReturnValue({
        data: [mockPlatformManager],
        isLoading: false,
        error: null,
      });

      render(<PlatformStaff />, { wrapper: createWrapper() });

      const addButton = screen.getByText('Add Staff Member');
      await user.click(addButton);

      expect(alertSpy).toHaveBeenCalledWith('Create new staff member - coming soon');

      alertSpy.mockRestore();
    });
  });

  describe('Table Structure', () => {
    it('should render table with correct headers', () => {
      mockCurrentUser.mockReturnValue({ data: mockSuperuser });
      mockPlatformUsers.mockReturnValue({
        data: [mockPlatformManager],
        isLoading: false,
        error: null,
      });

      render(<PlatformStaff />, { wrapper: createWrapper() });

      expect(screen.getByText('Staff Member')).toBeInTheDocument();
      expect(screen.getByText('Role')).toBeInTheDocument();
      expect(screen.getByText('Permissions')).toBeInTheDocument();
      expect(screen.getByText('Status')).toBeInTheDocument();
      expect(screen.getByText('Last Login')).toBeInTheDocument();
      expect(screen.getByText('Actions')).toBeInTheDocument();
    });

    it('should render table rows for each staff member', () => {
      mockCurrentUser.mockReturnValue({ data: mockSuperuser });
      mockPlatformUsers.mockReturnValue({
        data: [mockPlatformManager, mockPlatformSupport],
        isLoading: false,
        error: null,
      });

      render(<PlatformStaff />, { wrapper: createWrapper() });

      const rows = screen.getAllByRole('row');
      // 1 header row + 2 data rows
      expect(rows.length).toBe(3);
    });
  });
});
