import api from "./api";

import {
  getAdminHeaders
} from "./adminAuthService";

/* =========================================================
   SUBMISSION LIST
   ========================================================= */

export const getAdminSubmissions =
  async ({
    page = 1,
    limit = 10,
    search = "",
    status = "",
    assignment = "all",
    reviewerId = ""
  } = {}) => {
    const response =
      await api.get(
        "/admin/submissions",
        {
          headers:
            getAdminHeaders(),

          params: {
            page,
            limit,

            search:
              search || undefined,

            status:
              status || undefined,

            assignment:
              assignment || "all",

            reviewer_id:
              reviewerId ||
              undefined
          }
        }
      );

    return response.data;
  };

/* =========================================================
   REVIEWERS
   ========================================================= */

export const getAdminReviewers =
  async () => {
    const response =
      await api.get(
        "/admin/submissions/reviewers",
        {
          headers:
            getAdminHeaders()
        }
      );

    return response.data;
  };

/* =========================================================
   ASSIGN OR REASSIGN SUBMISSION
   ========================================================= */

export const assignAdminSubmission =
  async (
    submissionId,
    {
      assigned_to,
      assignment_note = ""
    }
  ) => {
    if (!submissionId) {
      throw new Error(
        "A valid submission is required."
      );
    }

    const response =
      await api.patch(
        `/admin/submissions/${submissionId}/assign`,
        {
          assigned_to,
          assignment_note
        },
        {
          headers:
            getAdminHeaders()
        }
      );

    return response.data;
  };

/* =========================================================
   SUBMISSION DETAIL
   ========================================================= */

export const getAdminSubmissionDetail =
  async (
    submissionId
  ) => {
    if (!submissionId) {
      throw new Error(
        "A valid submission is required."
      );
    }

    const response =
      await api.get(
        `/admin/submissions/${submissionId}`,
        {
          headers:
            getAdminHeaders()
        }
      );

    return response.data;
  };

/* =========================================================
   START REVIEW
   ========================================================= */

export const startAdminSubmissionReview =
  async (
    submissionId,
    {
      review_note = ""
    } = {}
  ) => {
    if (!submissionId) {
      throw new Error(
        "A valid submission is required."
      );
    }

    const response =
      await api.patch(
        `/admin/submissions/${submissionId}/start-review`,
        {
          review_note
        },
        {
          headers:
            getAdminHeaders()
        }
      );

    return response.data;
  };

/* =========================================================
   APPROVE SUBMISSION
   ========================================================= */

export const approveAdminSubmission =
  async (
    submissionId,
    {
      review_note = ""
    } = {}
  ) => {
    if (!submissionId) {
      throw new Error(
        "A valid submission is required."
      );
    }

    const response =
      await api.patch(
        `/admin/submissions/${submissionId}/approve`,
        {
          review_note
        },
        {
          headers:
            getAdminHeaders()
        }
      );

    return response.data;
  };

/* =========================================================
   RETURN SUBMISSION
   ========================================================= */

export const returnAdminSubmission =
  async (
    submissionId,
    {
      return_reason
    }
  ) => {
    if (!submissionId) {
      throw new Error(
        "A valid submission is required."
      );
    }

    const response =
      await api.patch(
        `/admin/submissions/${submissionId}/return`,
        {
          return_reason
        },
        {
          headers:
            getAdminHeaders()
        }
      );

    return response.data;
  };

/* =========================================================
   REJECT SUBMISSION
   ========================================================= */

export const rejectAdminSubmission =
  async (
    submissionId,
    {
      rejection_reason
    }
  ) => {
    if (!submissionId) {
      throw new Error(
        "A valid submission is required."
      );
    }

    const response =
      await api.patch(
        `/admin/submissions/${submissionId}/reject`,
        {
          rejection_reason
        },
        {
          headers:
            getAdminHeaders()
        }
      );

    return response.data;
  };

/* =========================================================
   DOWNLOAD SUPPORTING DOCUMENT
   ========================================================= */

/* =========================================================
   DOWNLOAD SUPPORTING DOCUMENT
   ========================================================= */

export const downloadAdminSubmissionDocument =
  async (
    submissionId,
    document
  ) => {
    if (!submissionId) {
      throw new Error(
        "A valid submission is required."
      );
    }

    if (!document?.id) {
      throw new Error(
        "A valid supporting document is required."
      );
    }

    try {
      const response =
        await api.get(
          `/admin/submissions/${submissionId}/documents/${document.id}/download`,
          {
            headers:
              getAdminHeaders(),

            responseType:
              "blob",

            timeout:
              120000
          }
        );

      const contentDisposition =
        response.headers[
          "content-disposition"
        ];

      let fileName =
        document.original_file_name ||
        "supporting-document";

      if (
        contentDisposition
      ) {
        const utf8Match =
          contentDisposition.match(
            /filename\*=UTF-8''([^;]+)/i
          );

        const normalMatch =
          contentDisposition.match(
            /filename="?([^";]+)"?/i
          );

        if (
          utf8Match?.[1]
        ) {
          try {
            fileName =
              decodeURIComponent(
                utf8Match[1]
              );
          } catch {
            fileName =
              utf8Match[1];
          }
        } else if (
          normalMatch?.[1]
        ) {
          fileName =
            normalMatch[1];
        }
      }

      const objectUrl =
        window.URL
          .createObjectURL(
            response.data
          );

      const downloadLink =
        window.document
          .createElement(
            "a"
          );

      downloadLink.href =
        objectUrl;

      downloadLink.download =
        fileName;

      downloadLink.style.display =
        "none";

      window.document.body
        .appendChild(
          downloadLink
        );

      downloadLink.click();
      downloadLink.remove();

      window.setTimeout(
        () => {
          window.URL
            .revokeObjectURL(
              objectUrl
            );
        },
        1000
      );

      return response;
    } catch (
      requestError
    ) {
      const responseData =
        requestError.response
          ?.data;

      /*
       * Axios returns failed file requests as
       * Blob data because responseType is "blob".
       * Convert it back into a readable error.
       */

      if (
        typeof Blob !==
          "undefined" &&
        responseData instanceof
          Blob
      ) {
        try {
          const responseText =
            await responseData
              .text();

          let message =
            responseText;

          try {
            const parsedResponse =
              JSON.parse(
                responseText
              );

            message =
              parsedResponse
                ?.message ||
              responseText;
          } catch {
            /*
             * The response was plain text,
             * so retain responseText.
             */
          }

          if (message) {
            throw new Error(
              message
            );
          }
        } catch (
          blobError
        ) {
          if (
            blobError.message
          ) {
            throw blobError;
          }
        }
      }

      throw requestError;
    }
  };

  /* =========================================================
   STAFF RECORD EXPORT HELPERS
   ========================================================= */

const getResponseFileName = (
  response,
  fallback
) => {
  const contentDisposition =
    response.headers[
      "content-disposition"
    ];

  if (!contentDisposition) {
    return fallback;
  }

  const utf8Match =
    contentDisposition.match(
      /filename\*=UTF-8''([^;]+)/i
    );

  if (
    utf8Match?.[1]
  ) {
    try {
      return decodeURIComponent(
        utf8Match[1]
      );
    } catch {
      return utf8Match[1];
    }
  }

  const normalMatch =
    contentDisposition.match(
      /filename="?([^";]+)"?/i
    );

  return (
    normalMatch?.[1] ||
    fallback
  );
};

const saveBlobResponse = (
  response,
  fallback
) => {
  const objectUrl =
    window.URL
      .createObjectURL(
        response.data
      );

  const downloadLink =
    window.document
      .createElement(
        "a"
      );

  downloadLink.href =
    objectUrl;

  downloadLink.download =
    getResponseFileName(
      response,
      fallback
    );

  downloadLink.style.display =
    "none";

  window.document.body
    .appendChild(
      downloadLink
    );

  downloadLink.click();
  downloadLink.remove();

  window.setTimeout(
    () => {
      window.URL
        .revokeObjectURL(
          objectUrl
        );
    },
    1000
  );
};

/* =========================================================
   DOWNLOAD INDIVIDUAL STAFF PDF
   ========================================================= */

export const downloadAdminSubmissionPdf =
  async (
    submissionId
  ) => {
    if (!submissionId) {
      throw new Error(
        "A valid submission is required."
      );
    }

    const response =
      await api.get(
        `/admin/submissions/${submissionId}/export/pdf`,
        {
          headers:
            getAdminHeaders(),

          params: {
            disposition:
              "attachment"
          },

          responseType:
            "blob",

          timeout:
            120000
        }
      );

    saveBlobResponse(
      response,
      `staff-record-${submissionId}.pdf`
    );
  };

/* =========================================================
   OPEN INDIVIDUAL PDF FOR PRINTING
   ========================================================= */

export const openAdminSubmissionPdfForPrint =
  async (
    submissionId
  ) => {
    if (!submissionId) {
      throw new Error(
        "A valid submission is required."
      );
    }

    const previewWindow =
      window.open(
        "",
        "_blank"
      );

    if (!previewWindow) {
      throw new Error(
        "Allow pop-ups for this site to open the printable staff record."
      );
    }

    previewWindow.opener =
      null;

    previewWindow.document.write(
      `
        <p
          style="
            font-family: Arial, sans-serif;
            padding: 24px;
          "
        >
          Preparing printable staff record...
        </p>
      `
    );

    try {
      const response =
        await api.get(
          `/admin/submissions/${submissionId}/export/pdf`,
          {
            headers:
              getAdminHeaders(),

            params: {
              disposition:
                "inline"
            },

            responseType:
              "blob",

            timeout:
              120000
          }
        );

      const objectUrl =
        window.URL
          .createObjectURL(
            response.data
          );

      previewWindow.location
        .replace(
          objectUrl
        );

      window.setTimeout(
        () => {
          window.URL
            .revokeObjectURL(
              objectUrl
            );
        },
        10 * 60 * 1000
      );
    } catch (error) {
      previewWindow.close();

      throw error;
    }
  };

/* =========================================================
   EXPORT FILTERED STAFF RECORDS TO EXCEL
   ========================================================= */

export const exportAdminSubmissionsExcel =
  async ({
    search = "",
    status = "",
    assignment = "all",
    reviewerId = ""
  } = {}) => {
    const response =
      await api.get(
        "/admin/submissions/export/excel",
        {
          headers:
            getAdminHeaders(),

          params: {
            search:
              search ||
              undefined,

            status:
              status ||
              undefined,

            assignment:
              assignment ||
              "all",

            reviewer_id:
              reviewerId ||
              undefined
          },

          responseType:
            "blob",

          timeout:
            120000
        }
      );

    saveBlobResponse(
      response,
      "CAGD-Staff-Records.xlsx"
    );
  };

/* =========================================================
   EXPORT SELECTED APPROVED PDFs
   ========================================================= */

export const exportAdminSubmissionPdfBatch =
  async (
    submissionIds
  ) => {
    const normalizedIds =
      Array.isArray(
        submissionIds
      )
        ? submissionIds
            .map(Number)
            .filter(
              (
                submissionId
              ) =>
                Number.isInteger(
                  submissionId
                ) &&
                submissionId > 0
            )
        : [];

    if (
      normalizedIds.length ===
      0
    ) {
      throw new Error(
        "Select at least one approved staff record."
      );
    }

    const response =
      await api.post(
        "/admin/submissions/export/pdf-batch",
        {
          submission_ids:
            normalizedIds
        },
        {
          headers:
            getAdminHeaders(),

          responseType:
            "blob",

          timeout:
            180000
        }
      );

    saveBlobResponse(
      response,
      "CAGD-Approved-Staff-Records.zip"
    );
  };