import { bustItGetCache, itDelete, itFetch, itGetCached, itPost } from "@/fetchHelpers";
import { getCookieValue } from "@/router/guards";
import type { DocumentUploadData } from "@/types";

type FileData = {
  fields: Record<string, string>;
  url: string;
};

async function startFileUpload(fileData: DocumentUploadData, courseSessionId: string) {
  if (fileData === null || fileData.file === null) {
    return null;
  }
  return await itPost(`/api/core/document/start/`, {
    file_type: fileData.file.type,
    file_name: fileData.file.name,
    name: fileData.name,
    learning_sequence: fileData.learningSequence.id,
    course_session: courseSessionId,
  });
}

export async function uploadFile(fileData: FileData, file: File) {
  if (fileData.fields) {
    return s3Upload(fileData, file);
  } else {
    return directUpload(fileData, file);
  }
}

function directUpload(fileData: FileData, file: File) {
  const formData = new FormData();
  formData.append("file", file);

  const headers = {
    Accept: "application/json",
  } as HeadersInit;

  const options = {
    method: "POST",
    headers: headers,
    body: formData,
  };
  // @ts-ignore
  options.headers["X-CSRFToken"] = getCookieValue("csrftoken");

  return handleUpload(fileData.url, options);
}

function s3Upload(fileData: FileData, file: File) {
  const formData = new FormData();
  for (const [name, value] of Object.entries(fileData.fields)) {
    formData.append(name, value);
  }

  formData.append("file", file);

  const options = Object.assign({
    method: "POST",
    body: formData,
  });

  return handleUpload(fileData.url, options);
}

async function handleUpload(url: string, options: RequestInit) {
  const response = await itFetch(url, options);
  try {
    return await response.json();
  } catch (e) {
    return Promise.resolve(null);
  }
}

export async function uploadCircleDocument(
  data: DocumentUploadData,
  courseSessionId: string,
  bustCacheUrlKey = ""
) {
  if (data.file === null) {
    throw new Error("No file selected");
  }

  const startData = await startFileUpload(data, courseSessionId);

  await uploadFile(startData, data.file);
  const response = itPost(`/api/core/file/finish/`, {
    file_id: startData.file_id,
  });

  if (bustCacheUrlKey) {
    bustItGetCache(bustCacheUrlKey);
  }

  return response;
}

export async function deleteCircleDocument(documentId: string, bustCacheUrlKey = "") {
  const result = itDelete(`/api/core/document/${documentId}/`);
  if (bustCacheUrlKey) {
    bustItGetCache(bustCacheUrlKey);
  }
  return result;
}

export async function fetchCourseSessionDocuments(courseSessionId: string) {
  return itGetCached(`/api/core/document/list/${courseSessionId}/`);
}

type PresignResponse = {
  pre_sign: {
    url: string;
    fields: Record<string, string>;
  };
  file_info: {
    id: string;
    name: string;
    url: string;
  };
};

export async function presignUpload(file: File): Promise<PresignResponse> {
  return await itPost(`/api/core/storage/presign/`, {
    file_type: file.type,
    file_name: file.name,
  });
}
