/**
 * Copyright (c) Microsoft Corporation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import fs from 'fs';

import { test, expect, writeFiles } from './fixtures';

test.use({ mcpServerType: 'test-mcp' });

test('generator tools intent', async ({ startClient }) => {
  const { client } = await startClient();
  const { tools } = await client.listTools();
  const toolsWithIntent: string[] = [];
  for (const tool of tools) {
    if (tool.inputSchema.properties?.intent)
      toolsWithIntent.push(tool.name);
  }
  toolsWithIntent.sort();

  expect(toolsWithIntent).toContain('browser_click');
  expect(toolsWithIntent).toContain('browser_close');
  expect(toolsWithIntent).toContain('browser_drag');
  expect(toolsWithIntent).toContain('browser_evaluate');
  expect(toolsWithIntent).toContain('browser_file_upload');
  expect(toolsWithIntent).toContain('browser_fill_form');
  expect(toolsWithIntent).toContain('browser_handle_dialog');
  expect(toolsWithIntent).toContain('browser_hover');
  expect(toolsWithIntent).toContain('browser_mouse_click_xy');
  expect(toolsWithIntent).toContain('browser_mouse_drag_xy');
  expect(toolsWithIntent).toContain('browser_mouse_move_xy');
  expect(toolsWithIntent).toContain('browser_navigate');
  expect(toolsWithIntent).toContain('browser_navigate_back');
  expect(toolsWithIntent).toContain('browser_press_key');
  expect(toolsWithIntent).toContain('browser_press_sequentially');
  expect(toolsWithIntent).toContain('browser_resize');
  expect(toolsWithIntent).toContain('browser_run_code_unsafe');
  expect(toolsWithIntent).toContain('browser_select_option');
  expect(toolsWithIntent).toContain('browser_tabs');
});

test('generator_setup_page', async ({ startClient }) => {
  await writeFiles({
    'a.test.ts': `
      import { test, expect } from '@playwright/test';
      test.beforeEach(async ({ page }) => {
        await page.setContent('<button>Submit</button>');
      });
      test('template', async ({ page }) => {
      });
    `,
  });

  const { client } = await startClient();
  const response = await client.callTool({
    name: 'generator_setup_page',
    arguments: {
      plan: 'Test plan',
      seedFile: 'a.test.ts',
    },
  });

  expect(response).toHaveTextResponse(expect.stringContaining(`### Paused at end of test. ready for interaction

### Page state
- Page URL: about:blank
- Page Title:
- Page Snapshot:
\`\`\`yaml
- button "Submit" [ref=e2]
\`\`\`
`));

  await client.callTool({
    name: 'browser_click',
    arguments: {
      element: 'Submit button',
      target: 'e2',
      intent: 'Click submit button',
    },
  });

  expect(await client.callTool({
    name: 'generator_read_log',
    arguments: {},
  })).toHaveTextResponse(expect.stringContaining(`# Plan

Test plan

# Seed file: a.test.ts

\`\`\`ts


      import { test, expect } from '@playwright/test';
      test.beforeEach(async ({ page }) => {
        await page.setContent('<button>Submit</button>');
      });
      test('template', async ({ page }) => {
      });
    

\`\`\`

# Steps

### Click submit button
\`\`\`ts
await page.getByRole('button', { name: 'Submit' }).click();
\`\`\`


# Best practices
`));
});

test('click after generator_log_action', async ({ startClient }) => {
  await writeFiles({
    'a.test.ts': `
      import { test, expect } from '@playwright/test';
      test.beforeEach(async ({ page }) => {
        await page.setContent('<button>Submit</button>');
      });
      test('template', async ({ page }) => {
      });
    `,
  });

  const { client } = await startClient();
  await client.callTool({
    name: 'generator_setup_page',
    arguments: {
      plan: 'Test plan',
      seedFile: 'a.test.ts',
    },
  });

  expect(await client.callTool({
    name: 'browser_click',
    arguments: {
      element: 'Submit button',
      target: 'e2',
      intent: 'Click submit button',
    },
  })).toHaveResponse({
    code: `await page.getByRole('button', { name: 'Submit' }).click();`,
    snapshot: expect.stringContaining(`- button "Submit"`),
  });

  expect(await client.callTool({
    name: 'generator_read_log',
    arguments: {},
  })).toHaveTextResponse(expect.stringContaining(`# Plan

Test plan

# Seed file: a.test.ts

\`\`\`ts


      import { test, expect } from '@playwright/test';
      test.beforeEach(async ({ page }) => {
        await page.setContent('<button>Submit</button>');
      });
      test('template', async ({ page }) => {
      });
    

\`\`\`

# Steps

### Click submit button
\`\`\`ts
await page.getByRole('button', { name: 'Submit' }).click();
\`\`\`


# Best practices
`));
});

test('generator_setup_page is required', async ({ startClient }) => {
  await writeFiles({
    'a.test.ts': `
      import { test, expect } from '@playwright/test';
      test.beforeEach(async ({ page }) => {
        await page.setContent('<button>Submit</button>');
      });
      test('template', async ({ page }) => {
      });
    `,
  });

  const { client } = await startClient();

  expect(await client.callTool({
    name: 'generator_read_log',
    arguments: {},
  })).toEqual({
    content: [{ type: 'text', text: `Error: Please setup page using "generator_setup_page" first.` }],
    isError: true,
  });

  expect(await client.callTool({
    name: 'generator_write_test',
    arguments: {
      fileName: 'a.test.ts',
      code: '// Test content',
    },
  })).toEqual({
    content: [{ type: 'text', text: `Error: Please setup page using "generator_setup_page" first.` }],
    isError: true,
  });

  expect(await client.callTool({
    name: 'generator_read_log',
    arguments: {},
  })).toEqual({
    content: [{ type: 'text', text: `Error: Please setup page using "generator_setup_page" first.` }],
    isError: true,
  });
});

test('generator_write_test', async ({ startClient }, testInfo) => {
  await writeFiles({
    'a.test.ts': `
      import { test, expect } from '@playwright/test';
      test.beforeEach(async ({ page }) => {
        await page.setContent('<button>Submit</button>');
      });
      test('template', async ({ page }) => {
      });
    `,
  });

  const { client } = await startClient();

  await client.callTool({
    name: 'generator_setup_page',
    arguments: {
      plan: 'Test plan',
      seedFile: 'a.test.ts',
    },
  });

  expect(await client.callTool({
    name: 'generator_write_test',
    arguments: {
      fileName: 'a.test.ts',
      code: `// Test content`,
    },
  })).toHaveResponse({
    result: expect.stringContaining(`Test written to a.test.ts`),
  });

  const code = fs.readFileSync(testInfo.outputPath('a.test.ts'), 'utf8');
  expect(code).toBe(`// Test content`);
});

test('should respect custom test id', async ({ startClient }) => {
  await writeFiles({
    'playwright.config.ts': `
      import { defineConfig } from '@playwright/test';
      export default defineConfig({
        use: {
          testIdAttribute: 'data-tid'
        }
      });
    `,
    'a.test.ts': `
      import { test, expect } from '@playwright/test';
      test.beforeEach(async ({ page }) => {
        await page.setContent('<button data-tid="submit">Submit</button>');
      });
      test('template', async ({ page }) => {
      });
    `,
  });

  const { client } = await startClient();
  await client.callTool({
    name: 'generator_setup_page',
    arguments: {
      plan: 'Test plan',
      seedFile: 'a.test.ts',
    },
  });

  expect(await client.callTool({
    name: 'browser_click',
    arguments: {
      element: 'Submit button',
      target: 'e2',
      intent: 'Click submit button',
    },
  })).toHaveResponse({
    code: `await page.getByTestId('submit').click();`,
  });
});
