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

/*if (fs.existsSync("../../nationchains/tribes/conf.json")) {
  conf = require("../../nationchains/tribes/conf.json");
}*/
const conf = require(`${process.env.dirtown}/conf.json`);

/**
 * Pagan Management numeric Identity and Person  (Person = Pagan Id + tribe)
 *
 *
 *
 */

const Pagans = {};

Pagans.getalias = (alias) => {
  /**
   * @param {string} alias a alias that exist or not
   * @return {object}  { status: 200, ref:"pagans",msg:"aliasexist",data: { alias, publicKey } }
   *                   { status: 404, ref:"pagans",msg:"aliasdoesnotexist",data: { alias} }
   *
   **/
  console.log(`${conf.dirapi}/nationchains/pagans/itm/${alias}.json`);
  if (fs.existsSync(`${conf.dirapi}/nationchains/pagans/itm/${alias}.json`)) {
    return {
      status: 200,
      ref: "Pagans",
      msg: "aliasexist",
      data: fs.readJsonSync(
        `${conf.dirapi}/nationchains/pagans/itm/${alias}.json`
      ),
    };
  } else {
    return {
      status: 404,
      ref: "Pagans",
      msg: "aliasdoesnotexist",
      data: { alias },
    };
  }
};

Pagans.getperson = (alias, tribeid) => {
  /**
   * @param {string} alias  that exist
   * @param {string} tribeId that exist with a person alias
   * @return {object}  { status: 200, ref:"pagans",msg:"personexist",data: { person } }
   *                   { status: 404, ref:"pagans",msg:"persondoesnotexist",data: { person } }
   *
   **/
  if (
    fs.existsSync(`${conf.dirtown}/tribes/${tribeid}/person/itm/${alias}.json`)
  ) {
    const person = fs.readJsonSync(
      `${conf.dirtown}/tribes/${tribeid}/person/itm/${alias}.json`
    );
    delete person.auth;
    return {
      status: 200,
      ref: "Pagans",
      msg: "personexist",
      data: person,
    };
  } else {
    return {
      status: 404,
      ref: "Pagans",
      msg: "persondoesnotexist",
      data: { alias, tribeid },
    };
  }
};

Pagans.create = (alias, publicKey) => {
  /**
   * @param {string} alias a unique alias that identify an identity
   * @param {string} publicKey a publicKey
   * @return {object}  { status: 200, data: { alias, publicKey } }
   *         xhash was checked  by isauthenticated
   * @todo use Odmdb to add a pagan
   */
  let apxpagans = {};
  if (fs.existsSync(`${conf.dirapi}/nationchains/pagans/idx/alias_all.json`)) {
    apxpagans = fs.readJsonSync(
      `${conf.dirapi}/nationchains/pagans/idx/alias_all.json`
    );
  }
  apxpagans[alias] = { alias, publicKey };
  fs.outputJsonSync(
    `${conf.dirapi}/nationchains/pagans/idx/alias_all.json`,
    apxpagans
  );
  fs.outputJsonSync(`${conf.dirapi}/nationchains/pagans/itm/${alias}.json`, {
    alias,
    publicKey,
  });
  return { status: 200, ref:"Pagans", msg:"identitycreate",data: { alias, publicKey } };
};

Pagans.personupdate = (alias, tribe, persondata) => {
  //later use Odmdb ans schema person to manage this
  /**
   * @Param {string} alias pagan unique id
   * @Param {string} tribe tribe id in this town
   * @Param {object} persondata that respect /nationchains/schema/person.json  + nationchains/tribe/tribeid/schema/personextented.json
   * @return create or update a person /tribe/tribeid/person/alias.json
   */
  let person = {
    alias: alias,
    dt_create: dayjs(),
    accessrights: { profil: "user" },
  };
  if (
    fs.existsSync(
      `${process.env.dirtown}/tribes/${tribe}/person/itm/${alias}.json`
    )
  ) {
    person = fs.readJsonSync(
      `${process.env.dirtown}/tribes/${tribe}/person/itm/${alias}.json`
    );
    person.dt_update = dayjs();
  }
  Object.keys(persondata).forEach((d) => {
    person[d] = persondata[d];
  });
  //const checkjson= Checkjson.schema.data = (fs.readJsonSync(`${conf.dirapi}/nationchains/schema/person.json`, person, false)
  // if checkjson.status==200 create /update with odmdb to update index data
  // see odmdb that did all and return standard message
  fs.outputJSONSync(
    `${process.env.dirtown}/tribes/${tribe}/person/itm/${alias}.json`,
    person,
    {
      space: 2,
    }
  );
  return {
    status: 200,
    ref: "Pagans",
    msg: "successfullupdate",
    data: { tribe: tribe },
  };
};

Pagans.authenticatedetachedSignature = async (
  alias,
  pubK,
  detachedSignature,
  message
) => {
  /**
   *  Check that a message was signed with a privateKey from a publicKey
   *  This is not necessary if isAuthenticated, but can be usefull to double check
   *  @TODO finish it and implement it also in  /apxpagan.js for browser
   *  @alias {string} alias link to the publicKey
   *  @pubK {string} publiKey text format
   *  @detachedSignature  {string} a detachedsignatured get from apx.detachedSignature
   *  @message {string} the message signed
   *  @return {boolean} true the message was signed by alias
   *                    false the message was not signed by alias
   */
  const publicKey = await openpgp.readKey({ armoredKey: pubK });
  const msg = await openpgp.createMessage({ text: message });
  const signature = await openpgp.readSignature({
    armoredSignature: detachedSignature, // parse detached signature
  });
  const verificationResult = await openpgp.verify({
    msg, // Message object
    signature,
    verificationKeys: publicKey,
  });
  const { verified, keyID } = verificationResult.signatures[0];
  try {
    await verified; // throws on invalid signature
    console.log("Signed by key id " + keyID.toHex());
    return KeyId.toHex().alias == alias;
  } catch (e) {
    console.log("Signature could not be verified: " + e.message);
    return false;
  }
};

Pagans.keyrecovery = (tribeid, email) => {
  glob
    .GlobSync(`${conf.dirtown}/tribes/${tribeId}/Person/*.json`)
    .forEach((f) => {
      const person = fs.readJsonSync(f);
      if (person.recoveryauth && person.recoveryauth.email) {
        // send email (alias publickey privatekey )
      }
    });
  return { status: 200, ref: "Pagans", msg: "todo" };
};
module.exports = Pagans;
