import React, { useContext, useState } from "react";

import api from "../../services/manifestsAPI";

const ManifestsContext = React.createContext();

export const ManifestsProvider = ({ children }) => {
  const [busy, setBusy] = useState(false);
  const [manifests, setManifests] = useState([]);
  const [totalManifests, setTotalManifests] = useState(0);

  const getManifest = async (id, token) => {
    let result;

    try {
      setBusy(true);
      result = await api.getManifest(id, token);
      if (result.error)
        throw new Error(`Get manifests error. ${result.message}`);
    } finally {
      setBusy(false);
    }

    return result;
  };

  const getManifests = async (search, token) => {
    let result;

    try {
      setBusy(true);
      result = await api.getManifests(search, token);
      if (result.error)
        throw new Error(`Get manifests error. ${result.message}`);
      setManifests(result.data);
      if (search && search.offset === 0 && result.total) {
        setTotalManifests(result.total);
      }
    } finally {
      setBusy(false);
    }

    return result;
  };

  const updateManifest = async (id, data, token) => {
    validateManifestUpdate(data);

    let result;

    try {
      setBusy(true);
      result = await api.updateManifest(id, data, token);
      if (result.error)
        throw new Error(`Update manifest error. ${result.message}`);
    } finally {
      setBusy(false);
    }

    return result;
  }

  const deleteManifest = async (package_id, token) => {
    let result;

    try {
      setBusy(true);
      result = await api.deleteManifest(package_id, token);
      if (result.error)
        throw new Error(`Delete manifest error. ${result.message}`);

      const index = manifests.findIndex((element) => {
        return element.id === package_id;
      });
      manifests.splice(index, 1);
    } finally {
      setBusy(false);
    }

    return result;
  };

  const migrateManifest = async (package_id, token) => {
    let result;

    try {
      setBusy(true)
      result = await api.migrateManifest(package_id, token)
      if (result.error)
        throw new Error(`failed to migrate manifest. ${result.message}`);
    } finally {
      setBusy(false)
    }
    return result

  }

  return (
    <ManifestsContext.Provider
      value={{
        busy,
        manifests,
        totalManifests,
        migrateManifest,
        updateManifest,
        getManifest,
        getManifests,
        deleteManifest,
      }}
    >
      {children}
    </ManifestsContext.Provider>
  );
};

const validateManifestUpdate = (data) => {
  if (data == null) throw new Error("No manifest data");

  if (data.name == null || data.name.length > 255) throw new Error("Invalid manifest name");

  if (data.type == null || !["forced", "standard"].includes(data.type)) {
    throw new Error("Invalid manifest type");
  }

  if (data.active == null || typeof data.active !== "boolean") throw new Error("Invalid active boolean")
}

export const useManifestsContext = () => useContext(ManifestsContext);
