import { useHTTP } from "hooks";
import React, { createContext, PropsWithChildren, useContext } from "react";
import { pond } from "protobuf-ts/pond";
import { pondURL } from "./pond";
import { AxiosResponse } from "axios";
import { useGlobalState } from "providers";

export interface IGrainBagInterface {
  addGrainBag: (
    name: string,
    settings: pond.GrainBagSettings,
    otherTeam?: string
  ) => Promise<AxiosResponse<pond.AddGrainBagResponse>>;
  listGrainBags: (
    limit: number,
    offset: number,
    order?: "asc" | "desc",
    orderBy?: string,
    search?: string,
    keys?: string[],
    types?: string[],
    numerical?: boolean,
    otherTeam?: string
  ) => Promise<AxiosResponse<pond.ListGrainBagsResponse>>;
  updateGrainBag: (
    key: string,
    name: string,
    settings: pond.GrainBagSettings,
    otherTeam?: string
  ) => Promise<AxiosResponse<pond.UpdateGrainBagResponse>>;
  bulkUpdateGrainBags: (
    bags: pond.GrainBag[],
    otherTeam?: string
  ) => Promise<AxiosResponse<pond.BulkGrainBagUpdateResponse>>;
  getGrainBag: (key: string, otherTeam?: string) => Promise<AxiosResponse<pond.GetGrainBagResponse>>;
  removeGrainBag: (key: string, otherTeam?: string) => Promise<AxiosResponse<pond.RemoveGrainBagResponse>>;
  listHistory: (
    id: string,
    limit: number,
    offset: number,
    start?: string,
    end?: string,
    otherTeam?: string
  ) => Promise<AxiosResponse<pond.ListGrainBagHistoryResponse>>;
}

export const GrainBagAPIcontext = createContext<IGrainBagInterface>({} as IGrainBagInterface);

interface Props {}

export default function GrainBagProvider(props: PropsWithChildren<Props>) {
  const { children } = props;
  const { get, del, post, put } = useHTTP();
  const [{ as }] = useGlobalState();

  const addGrainBag = (name: string, settings: pond.GrainBagSettings, otherTeam?: string) => {
    const view = otherTeam ? otherTeam : as
    if (view) {
      return post<pond.AddGrainBagResponse>(
        pondURL("/grainbags?name=" + name + "&as=" + view),
        settings
      );
    }
    return post<pond.AddGrainBagResponse>(pondURL("/grainbags?name=" + name), settings);
  };

  const listGrainBags = (
    limit: number,
    offset: number,
    order?: "asc" | "desc",
    orderBy?: string,
    search?: string,
    keys?: string[],
    types?: string[],
    numerical?: boolean,
    otherTeam?: string
  ) => {
    let asText = "";
    const view = otherTeam ? otherTeam : as
    if (view) asText = "&as=" + view;
    return get<pond.ListGrainBagsResponse>(
      pondURL(
        "/grainbags?limit=" +
          limit +
          "&offset=" +
          offset +
          ("&order=" + (order ? order : "asc")) +
          ("&by=" + (orderBy ? orderBy : "key")) +
          (numerical ? "&numerical=true" : "") +
          (search ? "&search=" + search : "") +
          (keys ? "&keys=" + keys.toString() : "") +
          (types ? "&types=" + types.toString() : "") +
          asText
      )
    );
  };

  const updateGrainBag = (key: string, name: string, settings: pond.GrainBagSettings, otherTeam?: string) => {
    const view = otherTeam ? otherTeam : as
    if (view) {
      return put<pond.UpdateGrainBagResponse>(
        pondURL("/grainbags/" + key + "?as=" + view + "&name=" + name),
        settings
      );
    }
    return put<pond.UpdateGrainBagResponse>(
      pondURL("/grainbags/" + key + "?name=" + name),
      settings
    );
  };

  const bulkUpdateGrainBags = (bags: pond.GrainBag[], otherTeam?: string) => {
    const view = otherTeam ? otherTeam : as
    if (view)
      return put<pond.BulkGrainBagUpdateResponse>(pondURL("/bulkGrainBags/update?as=" + view), {
        bags: bags
      });
    return put<pond.BulkGrainBagUpdateResponse>(pondURL("/bulkGrainBags/update"), { bags: bags });
  };

  const removeGrainBag = (key: string, otherTeam?: string) => {
    const view = otherTeam ? otherTeam : as
    if (view) {
      return del<pond.RemoveGrainBagResponse>(pondURL("/grainbags/" + key + "?as=" + view));
    }
    return del<pond.RemoveGrainBagResponse>(pondURL("/grainbags/" + key));
  };

  const getGrainBag = (key: string, otherTeam?: string) => {
    const view = otherTeam ? otherTeam : as
    if (view) {
      return get<pond.GetGrainBagResponse>(pondURL("/grainbags/" + key + "?as=" + view));
    }
    return get<pond.GetGrainBagResponse>(pondURL("/grainbags/" + key));
  };

  const listHistory = (id: string, limit: number, offset: number, start?: string, end?: string, otherTeam?: string) => {
    const view = otherTeam ? otherTeam : as
    let url = pondURL(
      "/grainbags/" +
        id +
        "/history?limit=" +
        limit +
        "&offset=" +
        offset +
        (start && "&start=" + start) +
        (end && "&end=" + end)
    )
    if (view) {
      url = url + "?as=" + view
    }
    return get<pond.ListGrainBagHistoryResponse>(url);
  };

  return (
    <GrainBagAPIcontext.Provider
      value={{
        addGrainBag,
        listGrainBags,
        updateGrainBag,
        bulkUpdateGrainBags,
        removeGrainBag,
        getGrainBag,
        listHistory
      }}>
      {children}
    </GrainBagAPIcontext.Provider>
  );
}

export const useGrainBagAPI = () => useContext(GrainBagAPIcontext);
