define(["jquery", "core/ajax", "core/str", "quizaccess_quilgo/sentry"], ($, Ajax, Str, Sentry) => {
  let cmid;
  let quizid;
  let fileName;
  let exportBtn;
  let exportBtnText;
  let csvRows = [];
  let exportText = "";
  let exportingText = "";
  let csvRowsAmount = 0;
  let isOnDownloading = false;
  let exportMsg;

  const getDownloadProgressPct = () => {
    if (csvRowsAmount === 0) {
      return 0;
    }

    const downloadProgressPct = Math.round((csvRows.length / csvRowsAmount) * 100);
    return downloadProgressPct > 100 ? 100 : downloadProgressPct;
  };

  const fetchCsvQuizStructure = () => {
    const wsfunction = "quizaccess_quilgo_fetch_csv_quiz_structure";
    const params = {
      cmid: Number(cmid),
      quizid: Number(quizid),
    };
    const request = {
      methodname: wsfunction,
      args: params,
    };

    return Ajax.call([request])[0];
  };

  const fetchCsvRecords = (_quizstructure, _lastattemptid) => {
    const wsfunction = "quizaccess_quilgo_fetch_csv_records";
    const params = {
      cmid: Number(cmid),
      quizid: Number(quizid),
      quizstructure: _quizstructure,
      lastattemptid: _lastattemptid,
    };
    const request = {
      methodname: wsfunction,
      args: params,
    };

    return Ajax.call([request])[0];
  };

  const generateCsv = (data) => {
    const reportString = data
      .map((row) => row.map((entry) => `"${entry.toString().replace(/"/g, '""')}"`).join(","))
      .join("\r\n");

    const BOMUnicode = "\uFEFF";
    const csvBlobData = new Blob([`${BOMUnicode}${reportString}`], {
      type: "text/csv;charset=utf-8",
    });
    const downloadUrl = window.URL.createObjectURL(csvBlobData);
    const link = document.createElement("a");
    link.href = downloadUrl;
    link.setAttribute("download", `${fileName}.csv`);
    document.body.appendChild(link);
    link.click();
    link.remove();
  };

  const downloadCsv = async (_quizStructure = null, _lastattemptid = null) => {
    try {
      isOnDownloading = true;
      let quizStructure = _quizStructure;
      if (quizStructure == null) {
        quizStructure = await fetchCsvQuizStructure();
      }

      const { headers, rowsamount, rows, lastattemptid } = await fetchCsvRecords(
        quizStructure,
        _lastattemptid,
      );
      const parsedHeaders = JSON.parse(headers);
      const parsedRows = JSON.parse(rows);

      if (rowsamount != null) {
        csvRowsAmount = rowsamount;
      }

      csvRows = [...csvRows, ...parsedRows];
      exportBtnText.text(`${exportingText} (${getDownloadProgressPct()}%)`);
      if (parsedRows.length > 0 && lastattemptid != null) {
        downloadCsv(quizStructure, lastattemptid);
        return;
      }

      generateCsv([parsedHeaders, ...csvRows]);
      isOnDownloading = false;
    } catch (error) {
      isOnDownloading = false;
      exportMsg.removeClass("quilgo-hidden");
      Sentry.captureError(error);
    } finally {
      if (isOnDownloading === false) {
        csvRowsAmount = 0;
        csvRows = [];
        exportBtnText.text(exportText);
        exportBtn.toggleClass("disabled");
      }
    }
  };

  const initElements = async () => {
    const [_exportText, _exportingText] = await Promise.all([
      Str.get_string("report_table_export_proctoring_data", "quizaccess_quilgo"),
      Str.get_string("report_table_exporting_proctoring_data", "quizaccess_quilgo"),
    ]);
    exportText = _exportText;
    exportingText = _exportingText;
    exportBtn = $(".quilgo-export-csv-btn");
    exportBtnText = $(".quilgo-export-csv-text");
    exportMsg = $(".quilgo-export-csv-msg");

    exportBtn.on("click", async () => {
      if (isOnDownloading) {
        return;
      }

      exportBtnText.text(`${exportingText} (${getDownloadProgressPct()}%)`);
      exportBtn.toggleClass("disabled");
      exportMsg.addClass("quilgo-hidden");
      downloadCsv(null, null);
    });
  };

  return {
    init: (_sentryOptions, _cmid, _quizid, _filename) => {
      Sentry.init(_sentryOptions);
      try {
        initElements();
        cmid = _cmid;
        quizid = _quizid;
        fileName = _filename;
      } catch (err) {
        Sentry.captureError(err);
      }
    },
  };
});
