import { expect, expectAsync, tap } from '@push.rocks/tapbundle';
import { jestExpect } from '@push.rocks/tapbundle/node';
import { Qenv } from '@push.rocks/qenv';

import * as smartbucket from '../ts/index.js';

const testQenv = new Qenv('./', './.nogit/');

let testSmartbucket: smartbucket.SmartBucket;
let myBucket: smartbucket.Bucket;
let baseDirectory: smartbucket.Directory;

tap.test('should create a valid smartbucket', async () => {
  testSmartbucket = new smartbucket.SmartBucket({
    accessKey: await testQenv.getEnvVarOnDemandStrict('S3_ACCESSKEY'),
    accessSecret: await testQenv.getEnvVarOnDemandStrict('S3_ACCESSSECRET'),
    endpoint: await testQenv.getEnvVarOnDemandStrict('S3_ENDPOINT'),
  });
  expect(testSmartbucket).toBeInstanceOf(smartbucket.SmartBucket);
  myBucket = await testSmartbucket.getBucketByNameStrict(await testQenv.getEnvVarOnDemandStrict('S3_BUCKET'),);
  expect(myBucket).toBeInstanceOf(smartbucket.Bucket);
  expect(myBucket.name).toEqual('test-pushrocks-smartbucket');
});

tap.test('should clean all contents', async () => {
  await myBucket.cleanAllContents();
  expect(await myBucket.fastExists({ path: 'hithere/socool.txt' })).toBeFalse();
  expect(await myBucket.fastExists({ path: 'trashtest/trashme.txt' })).toBeFalse();
});

tap.test('should delete a file into the normally', async () => {
  const path = 'trashtest/trashme.txt';
  const file = await myBucket.fastPutStrict({
    path,
    contents: 'I\'m in the trash test content!',
  });
  const fileMetadata = await (await file.getMetaData()).metadataFile.getContents();
  console.log(fileMetadata.toString());
  expect(await file.getMetaData().then((meta) => meta.metadataFile.getJsonData())).toEqual({});
  await file.delete({ mode: 'permanent' });
  expect((await (await myBucket.getBaseDirectory()).listFiles()).length).toEqual(0);  
  expect((await (await myBucket.getBaseDirectory()).listDirectories()).length).toEqual(0);  
});

tap.test('should put a file into the trash', async () => {
  const path = 'trashtest/trashme.txt';
  const file = await myBucket.fastPutStrict({
    path,
    contents: 'I\'m in the trash test content!',
  });
  const fileMetadata = await (await file.getMetaData()).metadataFile.getContents();
  console.log(fileMetadata.toString());
  expect(await file.getMetaData().then((meta) => meta.metadataFile.getJsonData())).toEqual({});
  await file.delete({ mode: 'trash' });

  const getTrashContents = async () => {
    const trash = await myBucket.getTrash();
    const trashDir = await trash.getTrashDir();
    return await trashDir.listFiles();
  }

  const trashedFiles = await getTrashContents();
  expect(trashedFiles.length).toEqual(2);

  const trashedMetaFile = trashedFiles.find(file => file.name.endsWith('.metadata'));
  expect(trashedMetaFile).toBeDefined();
  expect(trashedMetaFile).toBeInstanceOf(smartbucket.File);

  jestExpect(await trashedMetaFile!.getJsonData()).toEqual({
    custom_recycle: {
      deletedAt: jestExpect.any(Number),
      originalPath: "trashtest/trashme.txt",
    },
  });
});

tap.test('should restore a file from trash', async () => {
  const baseDirectory = await myBucket.getBaseDirectory();
  const file = await baseDirectory.getFileStrict({
    path: 'trashtest/trashme.txt',
    getFromTrash: true
  });
  const trashFileMeta = await file.getMetaData();
  const data = await trashFileMeta.getCustomMetaData({
    key: 'recycle'
  });
  expect(file).toBeInstanceOf(smartbucket.File);
  await file.restore();
});


export default tap.start();