/* eslint-disable @typescript-eslint/explicit-function-return-type */
import { getPort, portNumbers, DefaultLogger } from "@api-client/core";
import { esbuildPlugin } from '@web/dev-server-esbuild';
import { OAuth2Server } from "oauth2-mock-server";
import {
  Server,
  Clients,
  Testing,
} from "@api-client/net-store";
import { rm } from 'node:fs/promises'
import { takeScreenshotPlugin } from "./test/plugins/takeScreenshotPlugin.js";

/** @typedef {import('@api-client/net-store').IServerConfiguration} IServerConfiguration */

const oauth2server = new OAuth2Server();
let oauth2env;
const logger = new DefaultLogger();
const singleWsClients = new Clients();
const singleStore = new Testing.TestStore(logger, singleWsClients, "test/store/single");
let singlePort;
let singleBaseUri;
let singleServer;

const filteredLogs = ['Running in dev mode', 'lit-html is in dev mode'];


export default /** @type {import("@web/test-runner").TestRunnerConfig} */ ({
  /** Test files to run */
  files: [
    "test/**/*.test.ts",
    // "test/amf/**/*.test.ts",
    // "test/elements/store/*.test.ts",
  ],

  /** Resolve bare module imports */
  nodeResolve: {
    exportConditions: ["browser", "production"],
  },

  /** Filter out lit dev mode logs */
  filterBrowserLogs(log) {
    for (const arg of log.args) {
      if (
        typeof arg === "string" &&
        filteredLogs.some((l) => arg.includes(l))
      ) {
        return false;
      }
    }
    return true;
  },

  /** Compile JS for older browsers. Requires @web/dev-server-esbuild plugin */
  // esbuildTarget: 'auto',

  /** Amount of browsers to run concurrently */
  concurrentBrowsers: 3,

  plugins: [
    esbuildPlugin({ ts: true, target: "es2020" }),
    takeScreenshotPlugin(),

    {
      name: "mock-api",
      serve(context) {
        if (context.path === "/test/env.js") {
          const data = {
            oauth2: oauth2env,
            store: {
              single: singleBaseUri,
            },
          };
          return `export default ${JSON.stringify(data)}`;
        }
        return undefined;
      },
    },

    {
      name: "servers",
      async serverStart() {
        // OAuth2
        const port = await getPort({ port: portNumbers(8000, 8100) });
        const jwtKey = await oauth2server.issuer.keys.generate("RS256");
        await oauth2server.start(port, "localhost");
        oauth2env = {
          port,
          jwtKey,
          issuer: oauth2server.issuer.url,
        };
        // API store
        singlePort = await getPort({ port: portNumbers(8000, 8100) });
        singleBaseUri = `http://localhost:${singlePort}/`;
        const singleUser = /** @type IServerConfiguration */ ({
          logger,
          portOrSocket: singlePort,
          host: "http://localhost",
          session: {
            secret: "abc-tests",
            expiresIn: "5d",
          },
          mode: "single-user",
          cors: {
            enabled: true,
            cors: {
              exposeHeaders: ["location"],
              allowHeaders: ["authorization", "content-type"],
            },
          },
        });
        singleServer = new Server(singleStore, singleWsClients, singleUser);
        await singleStore.initialize();
        await singleServer.initialize(Testing.TestsHttpRoute);
        await singleServer.start();
      },

      async serverStop() {
        await oauth2server.stop();
        await singleServer.stop();
        await singleStore.cleanup();
        await rm("test/store", { recursive: true, force: true });
      },
    },
  ],

  /** Amount of test files per browser to test concurrently */
  // concurrency: 10,

  /** Browsers to run tests on */
  // browsers: [
  //   playwrightLauncher({ product: 'chromium' }),
  //   playwrightLauncher({ product: 'firefox' }),
  //   playwrightLauncher({ product: 'webkit' }),
  // ],

  // See documentation for all available options

  testRunnerHtml: (testFramework) =>
    `<html class="theme-light">
    <head>
      <link rel="stylesheet" href="/test/visualization/lib/test-styles.css" />
      <!-- m3 styles -->
      <link rel="stylesheet" href="/src/styles/m3/tokens.css" data-theme="tokens" />
      <link rel="stylesheet" href="/src/styles/m3/theme.css" data-theme="light" />
    </head>
    <body>
      <script type="module" src="${testFramework}"></script>
    </body>
  </html>`,

  testFramework: {
    config: {
      timeout: 60000,
    },
  },
  browserStartTimeout: 20000,
  testsStartTimeout: 20000,
  testsFinishTimeout: 60000,
});
