/**
 * @vitest-environment jsdom
 */
import React from 'react';
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import { screen, waitFor, cleanup } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom';

import { renderWithProviders } from '../../utils/testWrapper';

const {
  mockGetTicketFieldOptions,
  mockGetAvailableStatuses,
  mockGetCategoriesByBoard,
  mockCreateInboundTicketDefaults,
  mockUpdateInboundTicketDefaults,
  mockGetAllPriorities,
  mockGetAllUsersBasic,
  mockGetIntegrationClients,
  mockGetUserAvatarUrlsBatchAction,
} = vi.hoisted(() => ({
  mockGetTicketFieldOptions: vi.fn(),
  mockGetAvailableStatuses: vi.fn(),
  mockGetCategoriesByBoard: vi.fn(),
  mockCreateInboundTicketDefaults: vi.fn(),
  mockUpdateInboundTicketDefaults: vi.fn(),
  mockGetAllPriorities: vi.fn(),
  mockGetAllUsersBasic: vi.fn(),
  mockGetIntegrationClients: vi.fn(),
  mockGetUserAvatarUrlsBatchAction: vi.fn(),
}));

vi.mock('@alga-psa/ui/components/settings/general/BoardPicker', () => ({
  __esModule: true,
  BoardPicker: ({
    id,
    boards = [],
    selectedBoardId,
    onSelect,
    placeholder,
  }: any) => (
    <select
      id={id}
      data-testid="board-picker"
      value={selectedBoardId || ''}
      onChange={(event) => onSelect(event.target.value || null)}
    >
      <option value="">{placeholder ?? 'Select Board'}</option>
      {boards.map((board: any) => (
        <option key={board.board_id || board.id} value={board.board_id || board.id}>
          {board.board_name || board.name}
        </option>
      ))}
    </select>
  ),
}));

vi.mock('@alga-psa/ui/components/ClientPicker', () => ({
  __esModule: true,
  ClientPicker: ({
    id,
    clients = [],
    selectedClientId,
    onSelect,
    placeholder,
  }: any) => (
    <select
      id={id}
      data-testid="client-picker"
      value={selectedClientId || ''}
      onChange={(event) => onSelect(event.target.value ? event.target.value : null)}
    >
      <option value="">{placeholder ?? 'Select Client'}</option>
      {clients.map((client: any) => (
        <option key={client.client_id || client.id} value={client.client_id || client.id}>
          {client.client_name || client.name}
        </option>
      ))}
    </select>
  ),
}));

vi.mock('@alga-psa/tickets/components/CategoryPicker', () => ({
  __esModule: true,
  default: ({ id = 'category-picker', selectedCategories = [], onSelect, placeholder, disabled }: any) => (
    <select
      id={id}
      data-testid="category-picker"
      value={selectedCategories[0] || ''}
      onChange={(event) => onSelect(event.target.value ? [event.target.value] : [])}
      placeholder={placeholder}
      disabled={disabled}
    >
      <option value="">{placeholder ?? 'Select category'}</option>
    </select>
  ),
}));

vi.mock('@alga-psa/ui/components', () => ({
  __esModule: true,
  PrioritySelect: ({
    id,
    options = [],
    value,
    onValueChange,
    placeholder,
  }: any) => (
    <select
      id={id}
      data-testid="priority-select"
      value={value || ''}
      onChange={(event) => onValueChange(event.target.value)}
    >
      <option value="">{placeholder ?? 'Select priority'}</option>
      {options.map((option: any) => (
        <option key={option.value} value={option.value}>
          {typeof option.label === 'string' ? option.label : option.value}
        </option>
      ))}
    </select>
  ),
}));

vi.mock('@alga-psa/ui/components/CustomSelect', () => ({
  __esModule: true,
  default: ({
    id,
    options = [],
    value,
    onValueChange,
    placeholder,
    disabled,
  }: any) => (
    <select
      id={id}
      data-testid={`${id}-select`}
      value={value || ''}
      onChange={(event) => onValueChange(event.target.value)}
      disabled={disabled}
    >
      <option value="">{placeholder ?? 'Select option'}</option>
      {options.map((option: any) => (
        <option key={option.value} value={option.value}>
          {typeof option.label === 'string' ? option.label : option.value}
        </option>
      ))}
    </select>
  ),
}));

vi.mock('@alga-psa/ui/components/UserPicker', () => ({
  __esModule: true,
  default: ({ id, value, onValueChange, placeholder, users = [], disabled }: any) => (
    <select
      id={id}
      data-testid="user-picker"
      value={value || ''}
      onChange={(event) => onValueChange(event.target.value)}
      placeholder={placeholder}
      disabled={disabled}
    >
      <option value="">{placeholder ?? 'Select user'}</option>
      {users.map((user: any) => (
        <option key={user.user_id || user.id} value={user.user_id || user.id}>
          {user.full_name || user.display_name || user.username || 'User'}
        </option>
      ))}
    </select>
  ),
}));

vi.mock('@alga-psa/integrations/actions', () => ({
  __esModule: true,
  getTicketFieldOptions: mockGetTicketFieldOptions,
  getAvailableStatuses: mockGetAvailableStatuses,
  getCategoriesByBoard: mockGetCategoriesByBoard,
  createInboundTicketDefaults: mockCreateInboundTicketDefaults,
  updateInboundTicketDefaults: mockUpdateInboundTicketDefaults,
}));

vi.mock('../../../../../packages/integrations/src/actions/clientLookupActions', () => ({
  __esModule: true,
  getIntegrationClients: mockGetIntegrationClients,
}));

vi.mock('@alga-psa/reference-data/actions', () => ({
  __esModule: true,
  getAllPriorities: mockGetAllPriorities,
}));

vi.mock('@alga-psa/user-composition/actions', () => ({
  __esModule: true,
  getAllUsersBasic: mockGetAllUsersBasic,
  getUserAvatarUrlsBatchAction: mockGetUserAvatarUrlsBatchAction,
}));

import { InboundTicketDefaultsForm } from '../../../../../packages/integrations/src/components/email/forms/InboundTicketDefaultsForm';

const sampleFieldOptions = {
  boards: [
    { id: 'board-1', name: 'General', is_default: true },
    { id: 'board-2', name: 'Projects', is_default: false },
  ],
  statuses: [{ id: 'legacy-status', name: 'Legacy', is_default: false }],
  priorities: [{ id: 'priority-1', name: 'Medium' }],
  categories: [],
  clients: [{ id: 'client-1', name: 'Acme Corp' }],
  users: [],
  locations: [],
};

const sampleClients = [
  { client_id: 'client-1', client_name: 'Acme Corp', is_inactive: false },
];

const samplePriorities = [
  { priority_id: 'priority-1', priority_name: 'Medium', color: '#cccccc' },
];

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

    mockGetTicketFieldOptions.mockResolvedValue({ options: sampleFieldOptions });
    mockGetAvailableStatuses.mockImplementation(async (boardId: string | null) => {
      if (boardId === 'board-1') {
        return {
          statuses: [{ id: 'status-1', name: 'New', is_default: true }],
        };
      }

      if (boardId === 'board-2') {
        return {
          statuses: [{ id: 'status-2', name: 'Escalated', is_default: false }],
        };
      }

      return { statuses: [] };
    });
    mockGetCategoriesByBoard.mockResolvedValue({ categories: [] });
    mockGetIntegrationClients.mockResolvedValue(sampleClients);
    mockGetAllPriorities.mockResolvedValue(samplePriorities);
    mockGetAllUsersBasic.mockResolvedValue([]);
    mockGetUserAvatarUrlsBatchAction.mockResolvedValue({});
  });

  afterEach(() => {
    cleanup();
  });

  it('prevents submission when board is not selected', async () => {
    const user = userEvent.setup();

    renderWithProviders(
      <InboundTicketDefaultsForm
        defaults={null}
        onSuccess={vi.fn()}
        onCancel={vi.fn()}
      />
    );

    await waitFor(() => expect(mockGetTicketFieldOptions).toHaveBeenCalled());

    const shortNameInput = await screen.findByPlaceholderText('email-general');
    const displayNameInput = screen.getByPlaceholderText('General Email Support');
    const prioritySelect = screen.getByLabelText('Priority *');
    const clientSelect = screen.getByLabelText('Client *');

    await user.type(shortNameInput, 'catch-all');
    await user.type(displayNameInput, 'Catch All Defaults');
    await user.selectOptions(prioritySelect, 'priority-1');
    await user.selectOptions(clientSelect, 'client-1');

    await user.click(screen.getByRole('button', { name: 'Create Defaults' }));

    await waitFor(() => {
      expect(screen.getByText('Board is required')).toBeInTheDocument();
    });

    expect(mockCreateInboundTicketDefaults).not.toHaveBeenCalled();
  });

  it('prevents submission when company is not selected', async () => {
    const user = userEvent.setup();

    renderWithProviders(
      <InboundTicketDefaultsForm
        defaults={null}
        onSuccess={vi.fn()}
        onCancel={vi.fn()}
      />
    );

    await waitFor(() => expect(mockGetTicketFieldOptions).toHaveBeenCalled());

    const shortNameInput = await screen.findByPlaceholderText('email-general');
    const displayNameInput = screen.getByPlaceholderText('General Email Support');
    const boardSelect = screen.getByLabelText('Board *');
    const statusSelect = screen.getByLabelText('Status *');
    const prioritySelect = screen.getByLabelText('Priority *');

    await user.type(shortNameInput, 'catch-all');
    await user.type(displayNameInput, 'Catch All Defaults');
    await user.selectOptions(boardSelect, 'board-1');
    await user.selectOptions(statusSelect, 'status-1');
    await user.selectOptions(prioritySelect, 'priority-1');

    await user.click(screen.getByRole('button', { name: 'Create Defaults' }));

    await waitFor(() => {
      expect(screen.getByText('Company is required')).toBeInTheDocument();
    });

    expect(mockCreateInboundTicketDefaults).not.toHaveBeenCalled();
  });

  it('T034: only loads statuses for the selected board and clears stale status selections when the board changes', async () => {
    const user = userEvent.setup();

    renderWithProviders(
      <InboundTicketDefaultsForm
        defaults={null}
        onSuccess={vi.fn()}
        onCancel={vi.fn()}
      />
    );

    await waitFor(() => expect(mockGetTicketFieldOptions).toHaveBeenCalled());

    const boardSelect = await screen.findByLabelText('Board *');
    const statusSelect = screen.getByLabelText('Status *') as HTMLSelectElement;

    expect(statusSelect).toBeDisabled();

    await user.selectOptions(boardSelect, 'board-1');

    await waitFor(() => {
      expect(mockGetAvailableStatuses).toHaveBeenCalledWith('board-1');
      expect(statusSelect).not.toBeDisabled();
      expect(screen.getByRole('option', { name: 'New (Default)' })).toBeInTheDocument();
    });

    expect(screen.queryByRole('option', { name: 'Escalated' })).not.toBeInTheDocument();

    await user.selectOptions(statusSelect, 'status-1');
    expect(statusSelect.value).toBe('status-1');

    await user.selectOptions(boardSelect, 'board-2');

    await waitFor(() => {
      expect(mockGetAvailableStatuses).toHaveBeenCalledWith('board-2');
      expect(statusSelect.value).toBe('');
      expect(screen.getByRole('option', { name: 'Escalated' })).toBeInTheDocument();
    });

    expect(screen.queryByRole('option', { name: 'New (Default)' })).not.toBeInTheDocument();
  });
});
