/*
 This file is part of GNU Taler
 (C) 2021-2023 Taler Systems S.A.

 GNU Taler 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; either version 3, or (at your option) any later version.

 GNU Taler 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
 GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */

/**
 *
 * @author Sebastian Javier Marchano (sebasjm)
 */

import { MockEnvironment } from "@gnu-taler/web-util/lib/tests/mock";
import { ComponentChildren, FunctionalComponent, h, VNode } from "preact";
import { SWRConfig } from "swr";
import { ApiContextProvider } from "../context/api.js";
import { BackendContextProvider } from "../context/backend.js";
import { InstanceContextProvider } from "../context/instance.js";
import { HttpResponseOk, RequestOptions } from "../utils/request.js";

export class ApiMockEnvironment extends MockEnvironment {
  constructor(debug = false) {
    super(debug);
  }

  mockApiIfNeeded(): void {
    null; // do nothing
  }

  public buildTestingContext(): FunctionalComponent<{
    children: ComponentChildren;
  }> {
    const __SAVE_REQUEST_AND_GET_MOCKED_RESPONSE =
      this.saveRequestAndGetMockedResponse.bind(this);

    return function TestingContext({
      children,
    }: {
      children: ComponentChildren;
    }): VNode {
      async function request<T>(
        base: string,
        path: string,
        options: RequestOptions = {},
      ): Promise<HttpResponseOk<T>> {
        const _url = new URL(`${base}${path}`);
        // Object.entries(options.params ?? {}).forEach(([key, value]) => {
        //   _url.searchParams.set(key, String(value));
        // });

        const mocked = __SAVE_REQUEST_AND_GET_MOCKED_RESPONSE(
          {
            method: options.method ?? "GET",
            url: _url.href,
          },
          {
            qparam: options.params,
            auth: options.token,
            request: options.data,
          },
        );

        return {
          ok: true,
          data: (!mocked ? undefined : mocked.payload) as T,
          loading: false,
          clientError: false,
          serverError: false,
          info: {
            hasToken: !!options.token,
            status: !mocked ? 200 : mocked.status,
            url: _url,
            payload: options.data,
          },
        };
      }
      const SC: any = SWRConfig;

      return (
        <BackendContextProvider
          defaultUrl="http://backend"
          initialToken={undefined}
        >
          <InstanceContextProvider
            value={{
              token: undefined,
              id: "default",
              admin: true,
              changeToken: () => null,
            }}
          >
            <ApiContextProvider value={{ request }}>
              <SC
                value={{
                  loadingTimeout: 0,
                  dedupingInterval: 0,
                  shouldRetryOnError: false,
                  errorRetryInterval: 0,
                  errorRetryCount: 0,
                  provider: () => new Map(),
                }}
              >
                {children}
              </SC>
            </ApiContextProvider>
          </InstanceContextProvider>
        </BackendContextProvider>
      );
    };
  }
}
