const fs = require("fs-extra");
const dayjs = require("dayjs");
const glob = require("glob");
const openpgp = require("openpgp");

const conf = require(`${process.env.dirtown}/conf.json`);

const isAuthenticated = async (req, res, next) => {
  // tokens if valid are store in /dirtown/tmp/tokens/xalias_xdays_xhash(20,200) 
  // once a day rm oldest tokens than 24hours tag job by adding tmp/tokensmenagedone{day}
  const currentday = dayjs().date();
  console.log(
    "if menagedone" + currentday,
    !fs.existsSync(`${process.env.dirtown}/tmp/tokensmenagedone${currentday}`)
  );
  if (!fs.existsSync(`${process.env.dirtown}/tmp/tokens`))
    fs.mkdirSync(`${process.env.dirtown}/tmp/tokens`);
  if (!fs.existsSync(`${process.env.dirtown}/tmp/tokensmenagedone${currentday}`)) {
    // clean oldest
    const tsday = dayjs().valueOf(); // now in timestamp format
    glob.sync(`${process.env.dirtown}/tmp/tokensmenagedone*`).forEach((f) => {
      fs.removeSync(f);
    });
    glob.sync(`${process.env.dirtown}/tmp/tokens/*.json`).forEach((f) => {
      if (tsday - parseInt(f.split("_")[1]) > 86400000) fs.remove(f);
    });
  }
  //Check register in tmp/tokens/
  console.log("isAuthenticate?");
  const resnotauth = {
    ref: "headers",
    msg: "notauthenticated",
    data: {
      xalias: req.session.header.xalias,
      xaliasexists: true,
    },
  };
  //console.log(req.session.header);
  if (req.session.header.xalias == "anonymous" || req.session.header.xhash == "anonymous") {
    console.log("alias anonymous means not auth");
    return res.status(401).json(resnotauth);
  }

  const tmpfs = `${process.env.dirtown}/tmp/tokens/${req.session.header.xalias}_${
    req.session.header.xdays
  }_${req.session.header.xhash.substring(20, 200)}`;
  //console.log(tmpfs);
  if (!fs.existsSync(tmpfs)) {
    // need to check detached sign
    let publickey;
    if (
      fs.existsSync(
        `${conf.dirapi}/nationchains/pagans/itm/${req.session.header.xalias}.json`
      )
    ) {
      const pagan = fs.readJsonSync(
        `${conf.dirapi}/nationchains/pagans/itm/${req.session.header.xalias}.json`
      );
      publickey = pagan.publicKey;
    } else {
      resnotauth.data.xaliasexists = false;
      if (req.body.publickey) {
        publickey = req.body.publickey;
      } else {
        console.log("alias unknown");
        return res.status(404).send(resnotauth);
      }
    }
    if (publickey.substring(0,10)!=="-----BEGIN"){
      console.log("Publickey is not valid as armored key:", publickey)
      return res.status(404).send(resnotauth);
    }
    if (Buffer.from(req.session.header.xhash, "base64").toString().substring(0,10)!=="-----BEGIN"){
      console.log("xhash conv is not valid as armored key:", Buffer.from(req.session.header.xhash, "base64").toString())
      return res.status(404).send(resnotauth);
    }
    let publicKey;
    try {
      publicKey = await openpgp.readKey({ armoredKey: publickey });
    }catch(err){
      console.log(erreur)
    }
      const msg = await openpgp.createMessage({
      text: `${req.session.header.xalias}_${req.session.header.xdays}`,
    });
    const signature = await openpgp.readSignature({
      armoredSignature: Buffer.from(
        req.session.header.xhash,
        "base64"
      ).toString(),
    });
    //console.log(msg);
    //console.log(signature);
    //console.log(publicKey);
    const checkauth = await openpgp.verify({
      message: msg,
      signature: signature,
      verificationKeys: publicKey,
    });
    //console.log(checkauth);
    //console.log(checkauth.signatures[0].keyID);
    //console.log(await checkauth.signatures[0].signature);
    //console.log(await checkauth.signatures[0].verified);

    const { check, keyID } = checkauth.signatures[0];
    try {
      await check; // raise an error if necessary
      fs.outputFileSync(tmpfs, req.session.header.xhash, "utf8");
    } catch (e) {
      resnotauth.msg = "signaturefailed";
      console.log("not auth fail sign");
      return res.status(401).send(resnotauth);
    }
  }
  console.log("Authenticated");
  next();
};
module.exports = isAuthenticated;
