import React from 'react';
import { cleanup, fireEvent, render, screen, waitFor, within } from '@testing-library/react';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

const mocks = vi.hoisted(() => ({ remove: vi.fn(), errorToast: vi.fn(), successToast: vi.fn() }));

vi.mock('../src/platform/features/security/permissionSetQueries', () => ({
  usePermissionSets: () => ({ data: [{ Id: 'set-test', Name: 'TestSet', Label: 'Test Set', IsCustom: true }], isLoading: false }),
  useCreatePermissionSet: () => ({ isPending: false }),
  useUpdatePermissionSet: () => ({ isPending: false }),
  useDeletePermissionSet: () => ({ mutateAsync: mocks.remove }),
}));
vi.mock('../src/platform/features/security/components/PermissionEditorModal', () => ({ PermissionEditorModal: () => null }));
vi.mock('@nexuscrm/host-sdk', () => ({ formatApiError: (error: Error) => ({ message: error.message }) }));
vi.mock('@nexuscrm/salesforce-crm-standard-frontend/platform/components/ui', async (importOriginal) => {
  const ui = await importOriginal<Record<string, unknown>>();
  // Keep the actual confirmation modal and portal; the standard test harness
  // supplies the list/toast boundaries, not the warning text or delete action.
  const { ConfirmationModal } = await import('../src/platform/components/modals/ConfirmationModal');
  return { ...ui, ConfirmationModal, useErrorToast: () => mocks.errorToast, useSuccessToast: () => mocks.successToast };
});

import { PermissionSetManager } from '../src/platform/pages/PermissionSetManager';

afterEach(cleanup);
beforeEach(() => {
  mocks.remove.mockReset().mockResolvedValue(undefined);
  mocks.errorToast.mockReset();
  mocks.successToast.mockReset();
});

function openDelete() {
  render(<PermissionSetManager />);
  fireEvent.click(within(screen.getByTitle('Delete')).getByRole('button'));
  return screen.getByRole('dialog', { name: 'Delete Permission Set' });
}

describe('PermissionSet permanent deletion confirmation', () => {
  it('warns about permanent owned-permission deletion and restrictive references before submission', () => {
    const dialog = openDelete();
    expect(dialog).toHaveTextContent('Permanently delete "Test Set" and its permissions?');
    expect(dialog).toHaveTextContent('This cannot be undone.');
    expect(dialog).toHaveTextContent('Remove user assignments and other references first.');
    expect(dialog).not.toHaveTextContent('also remove all user assignments');
    expect(mocks.remove).not.toHaveBeenCalled();
    fireEvent.click(within(dialog).getByRole('button', { name: 'Cancel' }));
    expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
    expect(mocks.remove).not.toHaveBeenCalled();
  });

  it('confirms through the existing delete mutation exactly once', async () => {
    const dialog = openDelete();
    fireEvent.click(within(dialog).getByRole('button', { name: 'Delete', exact: true }));
    await waitFor(() => expect(mocks.successToast).toHaveBeenCalledWith('Permission Set deleted successfully'));
    expect(mocks.remove).toHaveBeenCalledExactlyOnceWith('set-test');
    expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
  });

  it('keeps a reference rejection visible without pretending assignments were removed', async () => {
    mocks.remove.mockRejectedValue(new Error('Permission set is still referenced'));
    const dialog = openDelete();
    fireEvent.click(within(dialog).getByRole('button', { name: 'Delete', exact: true }));
    await waitFor(() => expect(mocks.errorToast).toHaveBeenCalledWith('Failed to delete permission set: Permission set is still referenced'));
    expect(mocks.successToast).not.toHaveBeenCalled();
    expect(screen.getByRole('dialog', { name: 'Delete Permission Set' })).toBeInTheDocument();
  });
});
