import {expect, test} from '@playwright/test';
import {WebMcpTool} from '../src/webmcp_types';
import {setupGedcomRoute} from './helpers';

const EXPECTED_TOOL_NAMES = [
  'get_selected_person',
  'search_indi',
  'inspect_indi',
  'focus_indi',
  'find_relationship_path',
  'get_ancestors',
  'get_descendants',
];

test.describe('WebMCP Integration', () => {
  test.beforeEach(async ({page, context}) => {
    await setupGedcomRoute(context);

    // Add init script to expose modelContext mock BEFORE application boots.
    await page.addInitScript(() => {
      const registeredTools: WebMcpTool[] = [];
      window.__registeredTools = registeredTools;
      window.navigator.modelContext = {
        registerTool: (tool: WebMcpTool) => {
          registeredTools.push(tool);
        },
        unregisterTool: (name: string) => {
          const idx = registeredTools.findIndex((t) => t.name === name);
          if (idx !== -1) registeredTools.splice(idx, 1);
        },
      };
    });
  });

  test('registers tools to standard modelContext', async ({page}) => {
    await page.goto('/#/view?url=https://example.org/family.ged');

    // Polling assertion to avoid React useEffect registration race condition.
    await page.waitForFunction(
      (expectedCount) => window.__registeredTools?.length === expectedCount,
      EXPECTED_TOOL_NAMES.length,
    );

    const toolNames = await page.evaluate(() =>
      window.__registeredTools
        ? window.__registeredTools.map((t) => t.name)
        : [],
    );
    expect(toolNames.sort()).toEqual([...EXPECTED_TOOL_NAMES].sort());
  });

  test('allows running focus_indi tool', async ({page}) => {
    await page.goto('/#/view?url=https://example.org/family.ged');
    await page.waitForFunction(
      (expectedCount) => window.__registeredTools?.length === expectedCount,
      EXPECTED_TOOL_NAMES.length,
    );

    await expect(page.locator('#content')).toContainText('Radobod');
    await expect(page.locator('#content')).not.toContainText('Chike');

    // Execute the non-serializable callback inside the browser environment.
    await page.evaluate(async () => {
      const focusTool = window.__registeredTools
        ? window.__registeredTools.find((t) => t.name === 'focus_indi')
        : null;
      if (!focusTool) throw new Error('focus_indi tool not found');
      await focusTool.execute({id: 'I21'}); // Shifts view focus to Chike.
    });

    // Verify that the UI updated automatically in response to the tool action.
    await expect(page.locator('#content')).toContainText('Chike');
  });
});
