/*
 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 
 */
import {
  HttpResponse,
  HttpResponseOk,
  HttpResponsePaginated,
  RequestError,
} from "@gnu-taler/web-util/browser";
import { useEffect, useState } from "preact/hooks";
import { MerchantBackend } from "../declaration.js";
import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils/constants.js";
import { useBackendInstanceRequest, useMatchMutate } from "./backend.js";
// FIX default import https://github.com/microsoft/TypeScript/issues/49189
import _useSWR, { SWRHook } from "swr";
const useSWR = _useSWR as unknown as SWRHook;
// const MOCKED_ACCOUNTS: Record = {
//   "hwire1": {
//     h_wire: "hwire1",
//     payto_uri: "payto://fake/iban/123",
//     salt: "qwe",
//   },
//   "hwire2": {
//     h_wire: "hwire2",
//     payto_uri: "payto://fake/iban/123",
//     salt: "qwe2",
//   },
// }
export function useBankAccountAPI(): BankAccountAPI {
  const mutateAll = useMatchMutate();
  const { request } = useBackendInstanceRequest();
  const createBankAccount = async (
    data: MerchantBackend.BankAccounts.AccountAddDetails,
  ): Promise> => {
    // MOCKED_ACCOUNTS[data.h_wire] = data
    // return Promise.resolve({ ok: true, data: undefined });
    const res = await request(`/private/accounts`, {
      method: "POST",
      data,
    });
    await mutateAll(/.*private\/accounts.*/);
    return res;
  };
  const updateBankAccount = async (
    h_wire: string,
    data: MerchantBackend.BankAccounts.AccountPatchDetails,
  ): Promise> => {
    // MOCKED_ACCOUNTS[h_wire].credit_facade_credentials = data.credit_facade_credentials
    // MOCKED_ACCOUNTS[h_wire].credit_facade_url = data.credit_facade_url
    // return Promise.resolve({ ok: true, data: undefined });
    const res = await request(`/private/accounts/${h_wire}`, {
      method: "PATCH",
      data,
    });
    await mutateAll(/.*private\/accounts.*/);
    return res;
  };
  const deleteBankAccount = async (
    h_wire: string,
  ): Promise> => {
    // delete MOCKED_ACCOUNTS[h_wire]
    // return Promise.resolve({ ok: true, data: undefined });
    const res = await request(`/private/accounts/${h_wire}`, {
      method: "DELETE",
    });
    await mutateAll(/.*private\/accounts.*/);
    return res;
  };
  return {
    createBankAccount,
    updateBankAccount,
    deleteBankAccount,
  };
}
export interface BankAccountAPI {
  createBankAccount: (
    data: MerchantBackend.BankAccounts.AccountAddDetails,
  ) => Promise>;
  updateBankAccount: (
    id: string,
    data: MerchantBackend.BankAccounts.AccountPatchDetails,
  ) => Promise>;
  deleteBankAccount: (id: string) => Promise>;
}
export interface InstanceBankAccountFilter {
}
export function useInstanceBankAccounts(
  args?: InstanceBankAccountFilter,
  updatePosition?: (id: string) => void,
): HttpResponsePaginated<
  MerchantBackend.BankAccounts.AccountsSummaryResponse,
  MerchantBackend.ErrorDetail
> {
  // return {
  //   ok: true,
  //   loadMore() { },
  //   loadMorePrev() { },
  //   data: {
  //     accounts: Object.values(MOCKED_ACCOUNTS).map(e => ({
  //       ...e,
  //       active: true,
  //     }))
  //   }
  // }
  const { fetcher } = useBackendInstanceRequest();
  const [pageAfter, setPageAfter] = useState(1);
  const totalAfter = pageAfter * PAGE_SIZE;
  const {
    data: afterData,
    error: afterError,
    isValidating: loadingAfter,
  } = useSWR<
    HttpResponseOk,
    RequestError
  >([`/private/accounts`], fetcher);
  const [lastAfter, setLastAfter] = useState<
    HttpResponse<
      MerchantBackend.BankAccounts.AccountsSummaryResponse,
      MerchantBackend.ErrorDetail
    >
  >({ loading: true });
  useEffect(() => {
    if (afterData) setLastAfter(afterData);
  }, [afterData /*, beforeData*/]);
  if (afterError) return afterError.cause;
  // if the query returns less that we ask, then we have reach the end or beginning
  const isReachingEnd =
    afterData && afterData.data.accounts.length < totalAfter;
  const isReachingStart = false;
  const pagination = {
    isReachingEnd,
    isReachingStart,
    loadMore: () => {
      if (!afterData || isReachingEnd) return;
      if (afterData.data.accounts.length < MAX_RESULT_SIZE) {
        setPageAfter(pageAfter + 1);
      } else {
        const from = `${afterData.data.accounts[afterData.data.accounts.length - 1]
          .h_wire
          }`;
        if (from && updatePosition) updatePosition(from);
      }
    },
    loadMorePrev: () => {
    },
  };
  const accounts = !afterData ? [] : (afterData || lastAfter).data.accounts;
  if (loadingAfter /* || loadingBefore */)
    return { loading: true, data: { accounts } };
  if (/*beforeData &&*/ afterData) {
    return { ok: true, data: { accounts }, ...pagination };
  }
  return { loading: true };
}
export function useBankAccountDetails(
  h_wire: string,
): HttpResponse<
  MerchantBackend.BankAccounts.BankAccountEntry,
  MerchantBackend.ErrorDetail
> {
  // return {
  //   ok: true,
  //   data: {
  //     ...MOCKED_ACCOUNTS[h_wire],
  //     active: true,
  //   }
  // }
  const { fetcher } = useBackendInstanceRequest();
  const { data, error, isValidating } = useSWR<
    HttpResponseOk,
    RequestError
  >([`/private/accounts/${h_wire}`], fetcher, {
    refreshInterval: 0,
    refreshWhenHidden: false,
    revalidateOnFocus: false,
    revalidateOnReconnect: false,
    refreshWhenOffline: false,
  });
  if (isValidating) return { loading: true, data: data?.data };
  if (data) {
    return data;
  }
  if (error) return error.cause;
  return { loading: true };
}