import { v4 as uuid } from 'uuid';
import { getIdentity } from '../auth/auth.ic';
import { createManagerActor, createStorageBucketActor, initStorageBucket } from '../../utils/manager.utils';
import { toNullable } from '../../utils/did.utils';
export const uploadFile = async ({ data, folder, maxSize }) => {
  const identity = getIdentity();
  return uploadFileIC({ data, folder, maxSize, identity });
};
export const uploadFileIC = async ({ data, maxSize, host, folder, identity }) => {
  if (!data || !data.name) {
    throw new Error('File not valid.');
  }
  if (data.size > maxSize) {
    throw new Error(`File is too big (max. ${maxSize / 1048576} Mb)`);
  }
  const { bucket, actor } = await getStorageBucket({ host, identity });
  const { fullPath, filename, token } = await upload({
    data,
    folder,
    storageBucket: actor
  });
  return {
    downloadUrl: `https://${bucket.toText()}.raw.ic0.app/${fullPath}?token=${token}`,
    fullPath,
    name: filename
  };
};
const getStorageBucket = async ({ host, identity }) => {
  if (!identity) {
    throw new Error('Invalid identity.');
  }
  const managerActor = await createManagerActor({ identity, host });
  const bucket = await initStorageBucket({ managerActor });
  const actor = await createStorageBucketActor({ identity, bucket, host });
  return {
    bucket,
    actor
  };
};
const uploadChunk = async ({ batchId, chunk, storageBucket }) => storageBucket.create_chunk({
  batchId,
  content: [...new Uint8Array(await chunk.arrayBuffer())]
});
const upload = async ({ data, folder, storageBucket }) => {
  const filename = encodeURI(data.name);
  const fullPath = `${folder}/${filename}`;
  const token = uuid();
  console.log('About to upload to the IC');
  const t0 = performance.now();
  const { batchId } = await storageBucket.create_batch({ name: filename, fullPath, token, folder });
  const t1 = performance.now();
  console.log('Upload create_batch', t1 - t0);
  const promises = [];
  const chunkSize = 700000;
  for (let start = 0; start < data.size; start += chunkSize) {
    const chunk = data.slice(start, start + chunkSize);
    promises.push(uploadChunk({
      batchId,
      chunk,
      storageBucket
    }));
  }
  const chunkIds = await Promise.all(promises);
  const t2 = performance.now();
  console.log('Upload upload chunks', t2 - t1);
  await storageBucket.commit_batch({
    batchId,
    chunkIds: chunkIds.map(({ chunkId }) => chunkId),
    contentType: data.type
  });
  const t3 = performance.now();
  console.log('Upload commit_batch', t3 - t2);
  console.log('Data uploaded', t3 - t0);
  return {
    fullPath,
    filename,
    token
  };
};
export const getFiles = async ({ folder }) => {
  const identity = getIdentity();
  const { bucket, actor } = await getStorageBucket({ identity });
  const assets = await actor.list(toNullable(folder));
  const host = `https://${bucket.toText()}.raw.ic0.app`;
  return {
    items: assets.map(({ name, fullPath, token }) => ({
      downloadUrl: `${host}/${fullPath}?token=${token}`,
      fullPath,
      name
    })),
    nextPageToken: null
  };
};
