import { Client } from "discord.js";

import axios from "axios";
import moment from "moment";
import path, { join } from "path";
import { Low, JSONFile } from "lowdb";
import dotenv from "dotenv";
import schedule from "node-schedule";
dotenv.config();

const __dirname = path.resolve();
// Use JSON file for storage
const file = join(__dirname, "db.json");
const adapter = new JSONFile(file);
const db = new Low(adapter);
const client = new Client();
// Read data from JSON file, this will set db.data content
await db.read();

// Initialize local DB
if (db.data === null) {
  // Set default data
  db.data = { config: {} };
  db.write();
}

//INIT

client.on("ready", () => {
  console.log(`Logged in as ${client.user.tag}!`);

  // find configured channel in cache or exit
  const name = db?.data?.storageProviderChannelName;
  const channel = client.channels.cache.find((c) => c?.name === name);
  if (!channel) {
    console.error(`Could not find channel '${name}'.`);
    process.exit(1);
  }

  const job = `0 */${db?.data?.reRunCronTimingInHour} * * *`;
  schedule.scheduleJob(job, () => announceSize(channel));
});

//UTILS

const generateSize = () => (isCacheOld() ? getSize() : db?.data?.config?.size);

let lastSize = 0;
const announceSize = async (channel) => {
  const response = await generateSize();
  if (lastSize === response) return;
  lastSize = response;
  const msg = `Current storage size: ${response}`;
  console.log(msg); // print a local copy
  channel.send(msg);
};

const generateMsg = async (msg = "", user = "") => {
  let size = await generateSize();
  msg.edit(`<@${user.id}>, Current storage size: ${size}`);
};

const getSize = async () => {
  let GB = await getSizeFromJoystream();
  if (!GB || GB.error) GB = await getSizeFromAPI();
  const size = `${GB} GB`;
  console.log(size);
  db.data.config[0] = { timeStamp: moment.utc().format(), size };
  db.write();
  return size;
};

const getSizeFromAPI = () =>
  axios
    .get(db.data?.dataURL)
    .then((response) => Math.round(response?.data?.data?.rows[0][0]))
    .catch((error) => console.warn("API failed", error));

const getSizeFromJoystream = () =>
  axios
    .get(db.data?.statusURL)
    .then((response) => Math.round(response.data.media.size / 1000000000))
    .catch((error) => console.warn("status endpoint failed", error));

const isCacheOld = () => {
  //returns true if the timestamp is older than 2 hours
  let lastTime = db.data?.config?.timeStamp;
  if (lastTime) {
    const today = moment();
    const diff = today.diff(lastTime, "minutes");
    console.log("Cache is old", diff, "minutes");
    return diff > 120;
  }
  return true;
};

// COMMANDS

client.on("message", async (msg) => {
  const user = msg.author;
  if (msg.content === "/storagesize") {
    msg
      .reply("Calculating... ")
      .then(async (oldMessage) => {
        generateMsg(oldMessage, user);
      })
      .catch((error) => {
        console.log("Not able to send message", error);
      });
  }
});

client.login(process.env.TOKEN);
