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

import assert from 'node:assert/strict';
import fs from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import {describe, it} from 'node:test';

import {lighthouseAudit} from '../../src/tools/lighthouse.js';
import {serverHooks} from '../server.js';
import {html, withMcpContext} from '../utils.js';

describe('lighthouse', () => {
  const server = serverHooks();
  describe('lighthouse_audit', () => {
    it('runs Lighthouse audit by default (navigation, desktop)', async () => {
      server.addHtmlRoute('/test', html`<div>Test</div>`);

      await withMcpContext(async (response, context) => {
        const page = context.getSelectedMcpPage().pptrPage;
        await page.goto(server.getRoute('/test'));

        await lighthouseAudit.handler(
          {
            params: {
              mode: 'navigation',
              device: 'desktop',
            },
            page: context.getSelectedMcpPage(),
          },
          response,
          context,
        );

        const data = response.attachedLighthouseResult;
        assert.ok(data);

        assert.ok(data.summary);
        assert.equal(data.summary.mode, 'navigation');
        assert.equal(data.summary.device, 'desktop');
        assert.ok(data.reports.length === 2); // json, html

        // Verify files exist
        for (const reportPath of data.reports) {
          const stats = await fs.stat(reportPath);
          assert.ok(stats.isFile());
        }
      });
    });

    it('restores emulation', async () => {
      server.addHtmlRoute('/test-mobile', html`<div>Test Mobile</div>`);

      await withMcpContext(async (response, context) => {
        const page = context.getSelectedMcpPage().pptrPage;
        await page.goto(server.getRoute('/test-mobile'));
        await context.getSelectedMcpPage().emulate({
          viewport: {
            width: 400,
            height: 400,
            deviceScaleFactor: 1,
            hasTouch: true,
          },
        });

        {
          const viewportData = await page.evaluate(() => {
            return {
              width: window.innerWidth,
              height: window.innerHeight,
              deviceScaleFactor: window.devicePixelRatio,
              hasTouch: navigator.maxTouchPoints > 0,
            };
          });

          assert.deepStrictEqual(viewportData, {
            width: 400,
            height: 400,
            deviceScaleFactor: 1,
            hasTouch: true,
          });
        }

        await lighthouseAudit.handler(
          {
            params: {
              mode: 'snapshot',
              device: 'mobile',
            },
            page: context.getSelectedMcpPage(),
          },
          response,
          context,
        );

        {
          const viewportData = await page.evaluate(() => {
            return {
              width: window.innerWidth,
              height: window.innerHeight,
              deviceScaleFactor: window.devicePixelRatio,
              hasTouch: navigator.maxTouchPoints > 0,
            };
          });

          assert.deepStrictEqual(viewportData, {
            width: 400,
            height: 400,
            deviceScaleFactor: 1,
            hasTouch: true,
          });
        }
      });
    });

    it('runs Lighthouse in snapshot mode with mobile device', async () => {
      server.addHtmlRoute('/test-mobile', html`<div>Test Mobile</div>`);

      await withMcpContext(async (response, context) => {
        const page = context.getSelectedMcpPage().pptrPage;
        await page.goto(server.getRoute('/test-mobile'));

        await lighthouseAudit.handler(
          {
            params: {
              mode: 'snapshot',
              device: 'mobile',
            },
            page: context.getSelectedMcpPage(),
          },
          response,
          context,
        );

        const data = response.attachedLighthouseResult;
        assert.ok(data);

        assert.equal(data.summary.mode, 'snapshot');
        assert.equal(data.summary.device, 'mobile');
        assert.ok(data.reports.length === 2);
      });
    });

    it('runs Lighthouse with custom output dir', async () => {
      server.addHtmlRoute('/test-mobile', html`<div>Test Mobile</div>`);

      const tmpDir = os.tmpdir();
      const folderPath = path.join(
        tmpDir,
        `temp-folder-${crypto.randomUUID()}`,
      );

      try {
        await withMcpContext(async (response, context) => {
          const page = context.getSelectedMcpPage().pptrPage;
          await page.goto(server.getRoute('/test-mobile'));

          await lighthouseAudit.handler(
            {
              params: {
                mode: 'snapshot',
                device: 'mobile',
                outputDirPath: folderPath,
              },
              page: context.getSelectedMcpPage(),
            },
            response,
            context,
          );

          const data = response.attachedLighthouseResult;
          assert.ok(data);
          assert.equal(data.summary.mode, 'snapshot');
          assert.equal(data.summary.device, 'mobile');
          assert.ok(data.reports.length === 2);
          for (const report of data.reports) {
            assert.ok(report.startsWith(folderPath));
          }
        });
      } finally {
        await fs.rm(folderPath, {recursive: true, force: true});
      }
    });
  });
});
