/**
 * @license
 * Copyright 2026 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

import assert from 'node:assert';
import {describe, it} from 'node:test';

import type {McpPage} from '../../src/McpPage.js';
import {listPages, navigatePage, selectPage} from '../../src/tools/pages.js';
import {executeWebMcpTool} from '../../src/tools/webmcp.js';
import {html, withMcpContext} from '../utils.js';

describe('webmcp', () => {
  describe('list_webmcp_tools', () => {
    it('list webmcp tools in navigate_page response', async () => {
      await withMcpContext(async (response, context) => {
        await navigatePage().handler(
          {params: {url: 'about:blank'}, page: context.getSelectedMcpPage()},
          response,
          context,
        );
        assert.ok(response.listWebMcpTools);
      });
    });

    it('list webmcp tools in list_pages response', async () => {
      await withMcpContext(async (response, context) => {
        await listPages().handler({params: {}}, response, context);
        assert.ok(response.listWebMcpTools);
      });
    });

    it('list webmcp tools in select_page response', async () => {
      await withMcpContext(async (response, context) => {
        const pageId = context.getSelectedMcpPage().id ?? 1;
        await selectPage.handler({params: {pageId}}, response, context);
        assert.ok(response.listWebMcpTools);
      });
    });
  });

  describe('execute_webmcp_tool', () => {
    async function setupWebMcpTool(page: McpPage) {
      await page.pptrPage.setContent(
        html`<form
            toolname="test_tool"
            tooldescription="A test tool"
            toolautosubmit
          ></form
          ><script>
            document.querySelector('form').onsubmit = event => {
              event.preventDefault();
              event.respondWith('hello');
            };
          </script>`,
      );
    }

    // TODO: Remove `.skip` once Chrome 149 reaches stable channel.
    it.skip('executes a tool successfully', async () => {
      await withMcpContext(
        async (response, context) => {
          const page = context.getSelectedMcpPage();
          await setupWebMcpTool(page);

          await executeWebMcpTool.handler(
            {params: {toolName: 'test_tool', input: JSON.stringify({})}, page},
            response,
            context,
          );
          assert.strictEqual(
            response.responseLines[0],
            JSON.stringify({status: 'Completed', output: 'hello'}, null, 2),
          );
        },
        {args: ['--enable-features=WebMCP,DevToolsWebMCPSupport']},
        {categoryExperimentalWebmcp: true},
      );
    });

    it('throws if tool is not found', async () => {
      await withMcpContext(
        async (response, context) => {
          await assert.rejects(
            async () => {
              await executeWebMcpTool.handler(
                {
                  params: {toolName: 'missing-tool', input: JSON.stringify({})},
                  page: context.getSelectedMcpPage(),
                },
                response,
                context,
              );
            },
            {message: /Tool missing-tool not found/},
          );
        },
        {args: ['--enable-features=WebMCP,DevToolsWebMCPSupport']},
        {categoryExperimentalWebmcp: true},
      );
    });

    it('throws if input is invalid', async () => {
      await withMcpContext(
        async (response, context) => {
          await assert.rejects(
            async () => {
              const page = context.getSelectedMcpPage();
              await setupWebMcpTool(page);

              await executeWebMcpTool.handler(
                {params: {toolName: 'test_tool', input: 'invalid'}, page},
                response,
                context,
              );
            },
            {
              message:
                /Failed to parse input as JSON: Unexpected token 'i', "invalid" is not valid JSON/,
            },
          );
        },
        {args: ['--enable-features=WebMCP,DevToolsWebMCPSupport']},
        {categoryExperimentalWebmcp: true},
      );
    });
  });
});
