const chainquery = require('chainquery');

module.exports = (sequelize, { BOOLEAN, DATE, FLOAT, INTEGER, STRING }) => {
  const Trending = sequelize.define(
    'Trending',
    {
      time: { /* TODO: Historical analysis and log roll */
        type        : DATE(6),
        defaultValue: sequelize.NOW,
      },
      isChannel: {
        type        : BOOLEAN,
        defaultValue: false,
      },
      claimId: {
        type        : STRING,
        defaultValue: null,
      },
      publisherId: {
        type        : STRING,
        defaultValue: null,
      },
      intervalViews: {
        type        : INTEGER,
        defaultValue: 0,
      },
      weight: {
        type        : FLOAT,
        defaultValue: 0,
      },
      zScore: {
        type        : FLOAT,
        defaultValue: 0,
      },
      pValue: {
        type        : FLOAT,
        defaultValue: 0,
      },
      // TODO: Calculate t-statistics
    },
    {
      freezeTableName: true,
      timestamps     : false, // don't use default timestamps columns
      indexes        : [
        {
          fields: ['claimId'],
        },
        {
          fields: ['time', 'isChannel', 'claimId', 'publisherId', 'weight'],
        },
      ],
    }
  );

  Trending.getTrendingWeightData = async ({
    hours = 2,
    minutes = 0,
    limit = 20,
  } = {}) => {
    let time = new Date();
    time.setHours(time.getHours() - hours);
    time.setMinutes(time.getMinutes() - minutes);

    const sqlTime = time.toISOString().slice(0, 19).replace('T', ' ');

    const selectString = 'DISTINCT(claimId), weight';
    const whereString = `isChannel = false and time > '${sqlTime}'`;
    const query = `SELECT ${selectString} FROM Trending WHERE ${whereString} ORDER BY weight DESC LIMIT ${limit}`;

    return sequelize.query(query, { type: sequelize.QueryTypes.SELECT });
  };

  Trending.getTrendingClaims = async () => {
    const trendingWeightData = await Trending.getTrendingWeightData();

    const trendingClaimIds = [];
    const trendingClaims = trendingWeightData.reduce((claims, trendingData) => {
      trendingClaimIds.push(trendingData.claimId);
      claims[trendingData.claimId] = {
        ...trendingData,
      };

      return claims;
    }, {});

    const claimData = await chainquery.claim.findAll({
      where: {
        claim_id: { [sequelize.Op.in]: trendingClaimIds },
      },
    });

    return claimData.map((claimData) => {
      return Object.assign(trendingClaims[claimData.claim_id], claimData.dataValues);
    });
  };

  return Trending;
};