import React from 'react';
import { act, cleanup, render, screen, waitFor } from '@testing-library/react';
import { MemoryRouter, Route, Routes } from 'react-router-dom';
import { afterEach, beforeEach, expect, it, vi } from 'vitest';
const lifecycle = vi.hoisted(() => ({ listeners: new Set<any>() }));
vi.mock('react-router-dom', () => import('@nexuscrm/test-real-router'));
vi.mock('@nexuscrm/host-sdk', async original => ({
    ...await original<any>(),
    useApp: () => ({ currentFrontendAppId: 'crm', refreshApps: async () => {} }),
    registerHostSessionLifecycleListener: (listener: any) => { lifecycle.listeners.add(listener); return () => lifecycle.listeners.delete(listener); },
}));
vi.mock('../src/platform/features/studio/components/StudioSidebar', () => ({ StudioSidebar: (props: any) => <div data-testid="object-choices">{props.availableObjects.map((object: any) => object.label).join(',')}</div> }));
vi.mock('../src/platform/features/studio/components/StudioObjectEditor', () => ({ StudioObjectEditor: () => null }));
vi.mock('../src/platform/features/studio/components/StudioDashboardEditor', () => ({ StudioDashboardEditor: () => null }));
vi.mock('../src/platform/features/studio/components/StudioPermissions', () => ({ StudioPermissions: () => null }));
import { setHostSessionTransportBridgeForTest } from '@nexuscrm/host-sdk';
import { apiClient } from '../src/platform/infrastructure/api/client';
import { STORAGE_KEYS } from '../src/platform/infrastructure/storage/storageKeys';
import { AppStudio } from '../src/platform/pages/AppStudio';
const json = (value: unknown) => new Response(JSON.stringify(value), { headers: { 'content-type': 'application/json' } });
beforeEach(() => {
    const values = new Map<string, string>();
    vi.stubGlobal('localStorage', { getItem: (key: string) => values.get(key) ?? null, setItem: (key: string, value: string) => values.set(key, value), removeItem: (key: string) => values.delete(key) });
    localStorage.setItem(STORAGE_KEYS.CONNECTION_MODE, 'backend'); apiClient.setSession('actor-a', '');
    setHostSessionTransportBridgeForTest({ prepareRequest: request => ({ route: 'host-backend', credentials: 'include', headers: request.headers, consumeResponse: () => {} }) });
});
afterEach(() => { cleanup(); expect(lifecycle.listeners.size).toBe(0); setHostSessionTransportBridgeForTest(undefined); apiClient.clearSession(); vi.unstubAllGlobals(); });
it.each(['replace', 'clear-then-login'])('loads only the new actor schema choices after %s with the real schema reader', async event => {
    let release!: (response: Response) => void; let schemaReads = 0, definitionReads = 0;
    vi.stubGlobal('fetch', vi.fn(async (url: string) => {
        const path = String(url);
        if (path.endsWith('/metadata/applications')) { definitionReads += 1; return json({ apps: [{ id: 'Sales', label: 'Sales' }] }); }
        if (path.endsWith('/app-navigation/Sales')) return json({ document: { application_id: 'Sales', revision: 1, items: [] } });
        if (path.endsWith('/analytics/dashboards')) return json({ dashboards: [] });
        if (path.endsWith('/sobjects')) {
            schemaReads += 1;
            if (schemaReads === 1) return new Promise<Response>(resolve => { release = resolve; });
            return json({ sobjects: [{ name: 'ActorB', label: 'Actor B choice' }] });
        }
        throw new Error(`Unexpected endpoint ${path}`);
    }));
    render(<MemoryRouter initialEntries={['/studio/Sales']}><Routes><Route path="/studio/:appId" element={<AppStudio dashboardWidgets={{} as any} />} /></Routes></MemoryRouter>);
    await waitFor(() => expect(schemaReads).toBe(1));
    if (event === 'clear-then-login') act(() => { for (const listener of lifecycle.listeners) listener.onCleared?.(); });
    act(() => {
        apiClient.setSession('actor-b', '');
        for (const listener of lifecycle.listeners) listener.onAuthenticated?.({ userId: 'actor-b' });
    });
    await waitFor(() => expect(definitionReads).toBe(2));
    await act(async () => { release(json({ sobjects: [{ name: 'ActorA', label: 'Actor A choice' }] })); });
    await waitFor(() => expect(screen.getByTestId('object-choices')).toHaveTextContent('Actor B choice'));
    expect(screen.getByTestId('object-choices')).not.toHaveTextContent('Actor A choice');
    expect(schemaReads).toBe(2);
});
