import { produce } from "immer";
import { ResultStore, useResultStore } from "@root/results/store";
import { RawResult, rawResultToResult } from "@model/result/result";
import { RequestQueue } from "@utils/requestQueue";
import { resultApi } from "@api/result";
import { devlog } from "@frontend/kitui";
import { enqueueSnackbar } from "notistack";
import { AxiosError } from "axios";
import { parseFilters } from "../../pages/QuizAnswersPage/helper";

const REQUEST_DEBOUNCE = 200;
const requestQueue = new RequestQueue();
let requestTimeoutId: ReturnType<typeof setTimeout>;

export const setResults = (results: RawResult | []) =>
  setProducedState(
    (state) => {
      state.results = Object.values(results)[1]?.map(rawResultToResult) ?? [];
      state.total_count = Object.values(results)[0];
    },
    {
      type: "setResults",
      results,
    }
  );

const removeResult = (resultId: number) =>
  setProducedState((state) => {
    const index = state.results.findIndex((r) => r.id === resultId);
    if (index === -1) return;

    state.results.splice(index, 1);
  });

export const deleteResult = async (resultId: number) =>
  requestQueue.enqueue(`deleteResult-${resultId}`, async () => {
    const result = useResultStore.getState().results.find((r) => r.id === resultId);
    if (!result) return;

    const [_, deleteError] = await resultApi.delete(Number(result.id));

    if (deleteError) {
      devlog("Error delete result", deleteError);
      enqueueSnackbar(deleteError);

      return;
    }

    removeResult(resultId);
  });

export const obsolescenceResult = async (resultId: number, editQuizId: number) => {
  requestQueue.enqueue(`obsolescenceResult-${resultId}-${editQuizId}`, async () => {
    const result = useResultStore.getState().results.find((r) => r.id === resultId);
    if (!result) return;
    if (result.new === false) return;
    let lossDebouncer: null | ReturnType<typeof setTimeout> = null;
    let lossId: number[] = [];
    if (!lossId.includes(resultId)) lossId.push(resultId);
    if (typeof lossDebouncer === "number") clearTimeout(lossDebouncer);
    lossDebouncer = setTimeout(async () => {
      //стреляем на лишение новизны
      const [_, obsolescenceError] = await resultApi.obsolescence(lossId);

      if (obsolescenceError) {
        devlog("Error", obsolescenceError);

        enqueueSnackbar(obsolescenceError);

        return;
      }

      lossId = [];
    }, 3000);
    const [resultList, resultError] = await resultApi.getList(editQuizId);

    if (resultError || !resultList) {
      return;
    }

    setResults(resultList);
  });
};

export const ExportResults = async (
  filterNew: string,
  filterDate: string,
  openPrePaymentModal: () => void,
  editQuizId: number
) => {
  const [data, resultError] = await resultApi.export(editQuizId, parseFilters(filterNew, filterDate));

  if (resultError) {
    if (resultError?.includes("Payment Required")) {
      openPrePaymentModal();
    }
    return;
  }

  const blob = new Blob([data as BlobPart], {
    type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8",
  });

  const link = document.createElement("a");
  link.href = window.URL.createObjectURL(data as Blob);
  link.download = `report_${new Date().getTime()}.xlsx`;
  link.click();
};

function setProducedState<A extends string | { type: string }>(recipe: (state: ResultStore) => void, action?: A) {
  useResultStore.setState((state) => produce(state, recipe), false, action);
}
