import React from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { render, screen } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';

const apiMocks = vi.hoisted(() => ({ workspace: vi.fn(), mutate: vi.fn(), getRecordTypes: vi.fn(), getProfiles: vi.fn() }));
vi.mock('../src/platform/infrastructure/api/layoutAuthoring', async importOriginal => ({
  ...await importOriginal<typeof import('../src/platform/infrastructure/api/layoutAuthoring')>(),
  layoutAuthoringAPI: { workspace: apiMocks.workspace, mutate: apiMocks.mutate },
}));
vi.mock('../src/platform/infrastructure/api/schemas', () => ({ getRecordTypes: apiMocks.getRecordTypes }));
vi.mock('../src/platform/infrastructure/api/users', () => ({
  usersAPI: { getProfiles: apiMocks.getProfiles },
}));

vi.mock('react-router-dom', async () => {
  const actual = await vi.importActual<Record<string, unknown>>('react-router-dom');
  return {
    ...actual,
    useParams: () => ({ objectApiName: 'Account' }),
    useNavigate: () => vi.fn(),
  };
});

import { LayoutManager } from '../src/platform/features/admin/components/layout/LayoutManager';

const layouts = [
  {
    id: 'account-default',
    layoutName: 'Primary Account Layout',
    objectApiName: 'Account',
    type: 'Detail',
    isDefault: true,
    createdDate: '2026-08-25T00:00:00Z',
    lastModifiedDate: '2026-08-25T00:00:00Z',
  },
  {
    id: 'account-secondary',
    layoutName: 'Secondary Account Layout',
    objectApiName: 'Account',
    type: 'Detail',
    isDefault: false,
    createdDate: '2026-08-25T00:00:00Z',
    lastModifiedDate: '2026-08-25T00:00:00Z',
  },
];

function renderManager() {
  const client = new QueryClient({ defaultOptions: { queries: { retry: false } } });
  return render(
    <QueryClientProvider client={client}>
      <LayoutManager />
    </QueryClientProvider>,
  );
}

beforeEach(() => {
  vi.clearAllMocks();
  apiMocks.workspace.mockResolvedValue({ objectId: 'Account', layoutRevision: `sha256:${'a'.repeat(64)}`,
    layouts: layouts.map(row => ({ layout_id: row.id, object_id: row.objectApiName, name: row.layoutName, type: row.type, is_default: row.isDefault })),
    assignments: [{ assignment_id: 'assignment-1', object_id: 'Account', layout_id: 'account-secondary', dimensions: [{ key: 'profile', value: 'profile-1' }], specificity: 1 }],
  });
  apiMocks.getProfiles.mockResolvedValue([{ Id: 'profile-1', Name: 'Standard User' }]);
  apiMocks.getRecordTypes.mockResolvedValue([]);
});

describe('Layout Manager reads one authoring workspace', () => {
  it('shows the real layouts, default and assignments and offers the completed authoring actions', async () => {
    renderManager();

    expect(await screen.findAllByText('Primary Account Layout')).not.toHaveLength(0);
    expect(screen.getAllByText('Secondary Account Layout')).not.toHaveLength(0);
    expect(screen.getByText('Standard User')).toBeInTheDocument();

    const viewButtons = screen.getAllByRole('button', { name: /^Edit$/ });
    expect(viewButtons).toHaveLength(2);
    viewButtons.forEach(button => expect(button).not.toBeDisabled());

    screen.getAllByRole('button', { name: /Clone/ }).forEach(button => {
      expect(button).not.toBeDisabled();
    });
    expect(screen.getByRole('button', { name: /Set .* as default/ })).not.toBeDisabled();
    expect(screen.getByRole('button', { name: /Delete Secondary Account Layout/ })).not.toBeDisabled();
    screen.getAllByRole('combobox').forEach(select => expect(select).not.toBeDisabled());
    expect(screen.getByText('Reload layouts')).toBeInTheDocument();
  });

  it('shows a layout service failure instead of an empty layout table', async () => {
    apiMocks.workspace.mockRejectedValue(new Error('catalog read unavailable'));

    renderManager();

    expect(await screen.findByText(/Failed to load layouts: catalog read unavailable/)).toBeInTheDocument();
    expect(screen.queryByRole('table')).not.toBeInTheDocument();
  });

  it('shows an assignment dependency failure instead of an empty matrix', async () => {
    apiMocks.getProfiles.mockRejectedValue(new Error('profile read unavailable'));

    renderManager();

    expect(await screen.findByText(/Failed to load profiles: profile read unavailable/)).toBeInTheDocument();
    expect(screen.queryByText('Standard User')).not.toBeInTheDocument();
  });
});
