const path = require("path");
const _ = require("lodash");
const logger = require("../utils/logger");
const client = require("../graphql-client/graphql-client").client;
const queries = require("../graphql-client/queries");

require("dotenv").config({
  path: path.resolve(process.cwd(), `.env.${process.env.NODE_ENV || "development"}`)
});

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

exports.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));
};

exports.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);
};

exports.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) {
    //delete images  returns.push(
    returns.push(
      await cloudinary.api.delete_resources(
        types.video.map((x) => x.key),
        { resource_type: "video" }
      )
    );
  }
  if (types.raw) {
    //delete images  returns.push(
    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(queries.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 });
  }
};

exports.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 {
          const res = {
            id: d.id,
            ...(await cloudinary.uploader.rename(d.from, d.to, {
              resource_type: DetermineFileType(d.type)
            }))
          };
          return res;
        } 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 succesfully moved on remote server. " });
  }
};

//Also needs to be updated in upload utility and mobile app.
function DetermineFileType(filetype) {
  if (!filetype) return "auto";
  else if (filetype.startsWith("image")) return "image";
  else if (filetype.startsWith("video")) return "video";
  else if (filetype.startsWith("application/pdf")) return "image";
  else if (filetype.startsWith("application")) return "raw";

  return "auto";
}
