const _ = require("lodash");
const logger = require("../utils/logger");
const client = require("../graphql-client/graphql-client").client;
const determineFileType = require("./util/determineFileType");
const { DELETE_MEDIA_DOCUMENTS } = require("../graphql-client/queries");

const cloudinary = require("cloudinary").v2;
cloudinary.config(process.env.CLOUDINARY_URL);

/**
 * @description Creates a signed upload URL for Cloudinary.
 * @param req
 * @param res
 */
const createSignedUploadURL = (req, res) => {
  logger.log("media-signed-upload", "DEBUG", req.user.email, null, null);
  res.send(cloudinary.utils.api_sign_request(req.body, process.env.CLOUDINARY_API_SECRET));
};

/**
 * @description Downloads files from Cloudinary.
 * @param req
 * @param res
 */
const downloadFiles = (req, res) => {
  const { ids } = req.body;

  logger.log("media-bulk-download", "DEBUG", req.user.email, ids, null);

  const url = cloudinary.utils.download_zip_url({
    public_ids: ids,
    flatten_folders: true
  });

  res.send(url);
};

/**
 * @description Deletes files from Cloudinary and Apollo.
 * @param req
 * @param res
 * @returns {Promise<void>}
 */
const deleteFiles = async (req, res) => {
  const { ids } = req.body;

  const types = _.groupBy(ids, (x) => determineFileType(x.type));

  logger.log("media-bulk-delete", "DEBUG", req.user.email, ids, null);

  const returns = [];

  if (types.image) {
    //delete images

    returns.push(
      await cloudinary.api.delete_resources(
        types.image.map((x) => x.key),
        { resource_type: "image" }
      )
    );
  }

  if (types.video) {
    returns.push(
      await cloudinary.api.delete_resources(
        types.video.map((x) => x.key),
        { resource_type: "video" }
      )
    );
  }

  if (types.raw) {
    returns.push(
      await cloudinary.api.delete_resources(
        types.raw.map((x) => `${x.key}.${x.extension}`),
        { resource_type: "raw" }
      )
    );
  }

  // Delete it on apollo.
  const successfulDeletes = [];

  returns.forEach((resType) => {
    Object.keys(resType.deleted).forEach((key) => {
      if (resType.deleted[key] === "deleted" || resType.deleted[key] === "not_found") {
        successfulDeletes.push(key.replace(/\.[^/.]+$/, ""));
      }
    });
  });

  try {
    const result = await client.request(DELETE_MEDIA_DOCUMENTS, {
      ids: ids.filter((i) => successfulDeletes.includes(i.key)).map((i) => i.id)
    });

    res.send({ returns, result });
  } catch (error) {
    logger.log("media-delete-error", "ERROR", req.user.email, null, [
      { ids, error: error.message || JSON.stringify(error) }
    ]);

    res.json({ error });
  }
};

/**
 * @description Renames keys in Cloudinary and updates the database.
 * @param req
 * @param res
 * @returns {Promise<void>}
 */
const renameKeys = async (req, res) => {
  const { documents, tojobid } = req.body;

  logger.log("media-bulk-rename", "DEBUG", req.user.email, null, documents);

  const proms = [];

  documents.forEach((d) => {
    proms.push(
      (async () => {
        try {
          return {
            id: d.id,
            ...(await cloudinary.uploader.rename(d.from, d.to, {
              resource_type: determineFileType(d.type)
            }))
          };
        } catch (error) {
          return { id: d.id, from: d.from, error: error };
        }
      })()
    );
  });

  let result;

  result = await Promise.all(proms);
  const errors = [];
  result
    .filter((d) => d.error)
    .forEach((d) => {
      errors.push(d);
    });

  let mutations = "";

  result
    .filter((d) => !d.error)
    .forEach((d, idx) => {
      //Create mutation text

      mutations =
        mutations +
        `
  update_doc${idx}:update_documents_by_pk(pk_columns: { id: "${d.id}" }, _set: {key: "${d.public_id}", jobid: "${tojobid}"}){
    id
   }
   `;
    });

  if (mutations !== "") {
    const mutationResult = await client.request(`mutation {
        ${mutations}
      }`);
    res.json({ errors, mutationResult });
  } else {
    res.json({ errors: "No images were successfully moved on remote server. " });
  }
};

module.exports = {
  createSignedUploadURL,
  downloadFiles,
  deleteFiles,
  renameKeys
};
