/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import { Server, StoreLevelUp, ProxyServer, Clients } from '@api-client/net-store';
import { DefaultLogger } from '@api-client/core';
import Secrets from './secrets.js';
import host from './IpAddress.js';

/** @typedef {import('@web/dev-server-core').Plugin} Plugin */
/** @typedef {import('@web/dev-server-core').ServerStartParams} ServerStartParams */
/** @typedef {import('@api-client/net-store').IServerConfiguration} IServerConfiguration */
/** @typedef {import('@api-client/net-store').IServerProxyConfiguration} IServerProxyConfiguration */

const logger = new DefaultLogger();
const singleWsClients = new Clients();
const multiWsClients = new Clients();
const singleStore = new StoreLevelUp(logger, singleWsClients, 'demo/store/single/data');
const multiStore = new StoreLevelUp(logger, multiWsClients, 'demo/store/multi/data');
const prefix = '/v1';
const singlePort = 8550;
const multiPort = 8551;
const proxyPort = 8553;
const singleBaseUri = `http://${host}:${singlePort}${prefix}`;
const multiBaseUri = `http://${host}:${multiPort}${prefix}`;
const multiRedirectUri = `http://home.api-client.dev:${multiPort}${prefix}`;
const proxyUri = `http://${host}:${proxyPort}${prefix}`;

const singleUser = /** @type IServerConfiguration */ ({
  logger,
  portOrSocket: singlePort,
  host,
  router: {
    prefix,
  },
  session: {
    secret: Secrets.secret,
    expiresIn: '5d',
  },
  mode: 'single-user',
  cors: {
    enabled: true,
    cors: {
      exposeHeaders: ['location'],
      allowHeaders: ['authorization', 'content-type'],
    },
  },
});

const multiUser = /** @type IServerConfiguration */ ({
  ...singleUser,
  mode: "multi-user",
  portOrSocket: multiPort,
  authentication: {
    type: "oidc",
    config: {
      issuerUri: "https://accounts.google.com/",
      clientId: Secrets.clientId,
      clientSecret: Secrets.clientSecret,
      redirectBaseUri: multiRedirectUri,
    },
  },
  logger,
  session: {
    expiresIn: "5d",
    secret: Secrets.secret,
  },
});

const proxyConfig = /** @type IServerProxyConfiguration */ ({
  port: proxyPort,
  prefix,
  logger,
  openRoute: true,
  cors: {
    enabled: true,
    cors: {
      exposeHeaders: ['location'],
      // allowHeaders: '*',
      allowMethods: 'GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS',
      origin: (ctx) =>  ctx.request.header.origin,
    },
  },
});

const singleServer = new Server(singleStore, singleWsClients, singleUser);
const multiServer = new Server(multiStore, multiWsClients, multiUser);
const proxyServer = new ProxyServer(proxyConfig);
const systemVariables = { ...process.env };

export default /** @type Plugin */ ({
  name: "api-store",
  /**
   * @param {ServerStartParams} args
   */
  async serverStart(args) {
    await singleStore.initialize();
    await singleServer.initialize();
    await singleServer.start();
    await multiStore.initialize();
    await multiServer.initialize();
    await multiServer.start();
    await proxyServer.start();

    console.log(`Running store: ${singleBaseUri}, ${multiBaseUri}`);
    console.log(`Running proxy: ${proxyUri}`);
  },

  async serverStop() {
    await singleServer.stop();
    await multiServer.stop();
    await proxyServer.stop();
    await singleStore.cleanup();
    await multiStore.cleanup();
  },

  serve(context) {
    if (context.path === "/demo/env.js") {
      const data = {
        proxyUri,
        store: {
          single: singleBaseUri,
          multi: multiBaseUri,
        },
        systemVariables,
      };
      return `export default ${JSON.stringify(data)}`;
    }
    return undefined;
  },
});
