/*
 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 { MerchantBackend } from "../declaration.js";
import { useMatchMutate, useBackendInstanceRequest } from "./backend.js";
import useSWR from "swr";
import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils/constants.js";
import { useEffect, useState } from "preact/hooks";
import {
  HttpError,
  HttpResponse,
  HttpResponseOk,
  HttpResponsePaginated,
} from "../utils/request.js";
export function useTemplateAPI(): TemplateAPI {
  const mutateAll = useMatchMutate();
  const { request } = useBackendInstanceRequest();
  const createTemplate = async (
    data: MerchantBackend.Template.TemplateAddDetails,
  ): Promise> => {
    const res = await request(`/private/templates`, {
      method: "POST",
      data,
    });
    await mutateAll(/.*private\/templates.*/);
    return res;
  };
  const updateTemplate = async (
    templateId: string,
    data: MerchantBackend.Template.TemplatePatchDetails,
  ): Promise> => {
    const res = await request(`/private/templates/${templateId}`, {
      method: "PATCH",
      data,
    });
    await mutateAll(/.*private\/templates.*/);
    return res;
  };
  const deleteTemplate = async (
    templateId: string,
  ): Promise> => {
    const res = await request(`/private/templates/${templateId}`, {
      method: "DELETE",
    });
    await mutateAll(/.*private\/templates.*/);
    return res;
  };
  const createOrder = async (
    templateId: string,
    data: MerchantBackend.Template.UsingTemplateDetails,
  ): Promise<
    HttpResponseOk
  > => {
    const res = await request(
      `/private/templates/${templateId}`,
      {
        method: "POST",
        data,
      },
    );
    await mutateAll(/.*private\/templates.*/);
    return res;
  };
  return { createTemplate, updateTemplate, deleteTemplate, createOrder };
}
export interface TemplateAPI {
  createTemplate: (
    data: MerchantBackend.Template.TemplateAddDetails,
  ) => Promise>;
  updateTemplate: (
    id: string,
    data: MerchantBackend.Template.TemplatePatchDetails,
  ) => Promise>;
  deleteTemplate: (id: string) => Promise>;
  createOrder: (
    id: string,
    data: MerchantBackend.Template.UsingTemplateDetails,
  ) => Promise>;
}
export interface InstanceTemplateFilter {
  //FIXME: add filter to the template list
  position?: string;
}
export function useInstanceTemplates(
  args?: InstanceTemplateFilter,
  updatePosition?: (id: string) => void,
): HttpResponsePaginated {
  const { templateFetcher } = useBackendInstanceRequest();
  // const [pageBefore, setPageBefore] = useState(1);
  const [pageAfter, setPageAfter] = useState(1);
  const totalAfter = pageAfter * PAGE_SIZE;
  // const totalBefore = args?.position !== undefined ? pageBefore * PAGE_SIZE : 0;
  /**
   * FIXME: this can be cleaned up a little
   *
   * the logic of double query should be inside the orderFetch so from the hook perspective and cache
   * is just one query and one error status
   */
  // const {
  //   data: beforeData,
  //   error: beforeError,
  //   isValidating: loadingBefore,
  // } = useSWR, HttpError>(
  //   [
  //     `/private/templates`,
  //     token,
  //     url,
  //     args?.position,
  //     totalBefore,
  //   ],
  //   templateFetcher,
  // );
  const {
    data: afterData,
    error: afterError,
    isValidating: loadingAfter,
  } = useSWR<
    HttpResponseOk,
    HttpError
  >([`/private/templates`, args?.position, -totalAfter], templateFetcher);
  //this will save last result
  // const [lastBefore, setLastBefore] = useState<
  //   HttpResponse
  // >({ loading: true });
  const [lastAfter, setLastAfter] = useState<
    HttpResponse
  >({ loading: true });
  useEffect(() => {
    if (afterData) setLastAfter(afterData);
    // if (beforeData) setLastBefore(beforeData);
  }, [afterData /*, beforeData*/]);
  // if (beforeError) return beforeError;
  if (afterError) return afterError;
  // if the query returns less that we ask, then we have reach the end or beginning
  const isReachingEnd =
    afterData && afterData.data.templates.length < totalAfter;
  const isReachingStart = false;
  // args?.position === undefined
  // ||
  // (beforeData && beforeData.data.templates.length < totalBefore);
  const pagination = {
    isReachingEnd,
    isReachingStart,
    loadMore: () => {
      if (!afterData || isReachingEnd) return;
      if (afterData.data.templates.length < MAX_RESULT_SIZE) {
        setPageAfter(pageAfter + 1);
      } else {
        const from = `${
          afterData.data.templates[afterData.data.templates.length - 1]
            .template_id
        }`;
        if (from && updatePosition) updatePosition(from);
      }
    },
    loadMorePrev: () => {
      // if (!beforeData || isReachingStart) return;
      // if (beforeData.data.templates.length < MAX_RESULT_SIZE) {
      //   setPageBefore(pageBefore + 1);
      // } else if (beforeData) {
      //   const from = `${beforeData.data.templates[beforeData.data.templates.length - 1]
      //     .template_id
      //     }`;
      //   if (from && updatePosition) updatePosition(from);
      // }
    },
  };
  const templates = !afterData ? [] : (afterData || lastAfter).data.templates;
  // const templates =
  //   !beforeData || !afterData
  //     ? []
  //     : (beforeData || lastBefore).data.templates
  //       .slice()
  //       .reverse()
  //       .concat((afterData || lastAfter).data.templates);
  if (loadingAfter /* || loadingBefore */)
    return { loading: true, data: { templates } };
  if (/*beforeData &&*/ afterData) {
    return { ok: true, data: { templates }, ...pagination };
  }
  return { loading: true };
}
export function useTemplateDetails(
  templateId: string,
): HttpResponse {
  const { templateFetcher } = useBackendInstanceRequest();
  const { data, error, isValidating } = useSWR<
    HttpResponseOk,
    HttpError
  >([`/private/templates/${templateId}`], templateFetcher, {
    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;
  return { loading: true };
}