const path = require("path");
const lotteryRepository = require(path.join(__dirname, "../lottery"));

const drawWinner = (req, res) => {
  return lotteryRepository
    .drawWinner()
    .then(({ winner, color, winners }) => {
      var io = req.app.get("socketio");
      io.emit("winner", {
        color: color,
        name: winner.name,
        winner_count: winners.length + 1
      });

      return { winner, color, winners };
    })
    .then(({ winner, color, winners }) =>
      res.send({
        color: color,
        winner: winner,
        success: true
      })
    )
    .catch(error => {
      const { statusCode, message } = error;

      return res.status(statusCode || 500).send({
        message: message || "Unexpected error occured while drawing winner.",
        success: false
      });
    });
};

const archiveLottery = (req, res) => {
  const { lottery } = req.body;
  if (lottery == undefined || !lottery instanceof Object) {
    return res.status(400).send({
      message: "Missing lottery object.",
      success: false
    });
  }

  let { stolen, date, raffles, wines } = lottery;
  stolen = stolen !== undefined ? stolen : 0; // default = 0
  date = date !== undefined ? date : new Date(); // default

  const validDateFormat = new RegExp("d{4}-d{2}-d{2}");
  if (!validDateFormat.test(date) || isNaN(date)) {
    return res.status(400).send({
      message: "Date must be defined as 'yyyy-mm-dd'.",
      success: false
    });
  } else {
    date = Date.parse(date, "yyyy-MM-dd");
  }

  return verifyLotteryPayload(raffles, stolen, wines)
    .then(_ => lottery.archive(date, raffles, stolen, wines))
    .catch(error => {
      const { statusCode, message } = error;

      return res.status(statusCode || 500).send({
        message: message || "Unexpected error occured while submitting lottery.",
        success: false
      });
    });
};

const lotteryByDate = (req, res) => {
  const { epoch } = req.params;

  if (!/^\d+$/.test(epoch)) {
    return res.status(400).send({
      message: "Last parameter must be epoch (in seconds).",
      success: false
    });
  }
  const date = new Date(Number(epoch) * 1000);

  return lotteryRepository
    .lotteryByDate(date)
    .then(lottery =>
      res.send({
        lottery,
        message: `Lottery for date: ${dateToDateString(date)}/${epoch}.`,
        success: true
      })
    )
    .catch(error => {
      const { statusCode, message } = error;

      return res.status(statusCode || 500).send({
        message: message || "Unexpected error occured while fetching lottery by date.",
        success: false
      });
    });
};

const allLotteries = (req, res) => {
  const isAdmin = req.isAuthenticated();

  return lotteryRepository
    .allLotteries(isAdmin)
    .then(lotteries =>
      res.send({
        lotteries,
        message: "All lotteries.",
        success: true
      })
    )
    .catch(error => {
      const { statusCode, message } = error;

      return res.status(statusCode || 500).send({
        message: message || "Unexpected error occured while fetching all lotteries.",
        success: false
      });
    });
};

function verifyLotteryPayload(raffles, stolen, wines) {
  return new Promise((resolve, reject) => {
    if (raffles == undefined || !raffles instanceof Array) {
      reject({
        message: "Raffles must be array.",
        status: 400
      });
    }

    const requiredColors = [raffles["red"], raffles["blue"], raffles["green"], raffles["yellow"]];
    const correctColorsTypes = requiredColors.filter(color => typeof color === "number");
    if (requiredColors.length !== correctColorsTypes.length) {
      reject({
        message:
          "Incorrect or missing raffle colors, required type Number for keys: 'blue', 'red', 'green' & 'yellow'.",
        status: 400
      });
    }

    if (stolen == undefined || (isNaN(stolen) && stolen >= 0)) {
      reject({
        message: "Number of stolen raffles must be positive integer or 0.",
        status: 400
      });
    }

    if (wines == undefined || !wines instanceof Array) {
      reject({
        message: "Wines must be array.",
        status: 400
      });
    }

    resolve();
  });
}

function dateToDateString(date) {
  const ye = new Intl.DateTimeFormat("en", { year: "numeric" }).format(date);
  const mo = new Intl.DateTimeFormat("en", { month: "2-digit" }).format(date);
  const da = new Intl.DateTimeFormat("en", { day: "2-digit" }).format(date);

  return `${ye}-${mo}-${da}`;
}

module.exports = {
  drawWinner,
  archiveLottery,
  lotteryByDate,
  allLotteries
};
