/*
 * Copyright (C) 2019 StApps
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */
import {SCPluginRegisterRequest, SCPluginRegisterResponse, SCPluginRegisterRoute} from '@openstapps/core';
import chai from 'chai';
import {expect} from 'chai';
import chaiSpies from 'chai-spies';
import {HttpClient, HttpClientResponse} from '@openstapps/api';
import {PluginClient} from '../src/index.js';
import {TestPlugin} from './plugin-resources/test-plugin.js';

chai.use(chaiSpies);

const sandbox = chai.spy.sandbox();

const httpClient = new HttpClient();
const pluginRegisterRoute = new SCPluginRegisterRoute();
const pluginClient = new PluginClient(httpClient, 'http://localhost');

describe('PluginClient', function () {
  this.timeout(10_000);

  let plugin: TestPlugin;

  beforeEach(async function () {
    plugin = new TestPlugin(
      4000,
      '',
      '',
      '',
      '',
      {
        getSchema: () => {
          /***/
        },
      } as never,
      '',
      '',
      '',
    );
  });

  afterEach(async function () {
    await plugin.close();
    sandbox.restore();
  });

  it('should register the plugin', async function () {
    sandbox.on(httpClient, 'request', async (): Promise<HttpClientResponse<SCPluginRegisterResponse>> => {
      return {
        body: {
          success: true,
        },
        headers: {},
        statusCode: pluginRegisterRoute.statusCodeSuccess,
      };
    });

    expect(httpClient.request).not.to.have.been.called();

    await pluginClient.registerPlugin(plugin);

    const request: SCPluginRegisterRequest = {
      action: 'add',
      plugin: {
        address: plugin.fullUrl,
        name: plugin.name,
        requestSchema: plugin.requestSchema,
        responseSchema: plugin.responseSchema,
        route: plugin.route,
      },
    };

    expect(httpClient.request).to.have.been.first.called.with({
      body: request,
      headers: {
        'Content-Type': 'application/json',
      },
      method: pluginRegisterRoute.method,
      url: new URL(`http://localhost${pluginRegisterRoute.getUrlPath()}`),
    });
  });

  it('should unregister the plugin', async function () {
    sandbox.on(httpClient, 'request', async (): Promise<HttpClientResponse<SCPluginRegisterResponse>> => {
      return {
        body: {
          success: true,
        },
        headers: {},
        statusCode: pluginRegisterRoute.statusCodeSuccess,
      };
    });

    expect(httpClient.request).not.to.have.been.called();

    await pluginClient.unregisterPlugin(plugin);

    const request: SCPluginRegisterRequest = {
      action: 'remove',
      route: plugin.route,
    };

    expect(httpClient.request).to.have.been.first.called.with({
      body: request,
      headers: {
        'Content-Type': 'application/json',
      },
      method: pluginRegisterRoute.method,
      url: new URL(`http://localhost${pluginRegisterRoute.getUrlPath()}`),
    });
  });
});
