/* eslint-disable no-plusplus */
/* eslint-disable no-continue */
/* eslint-disable default-case */
import moment from 'moment';
import { Message, User } from 'eris';
import { Client, Command, RichEmbed } from '../class';
import { getTotalMessageCount } from '../intervals/score';
import Score_Hist from './score_hist';
import Score_Notify from './score_notify';
import Score_Pref from './score_pref';

export default class Score extends Command {
  constructor(client: Client) {
    super(client);
    this.name = 'score';
    this.description = 'Retrieves your Community Report';
    this.usage = `${this.client.config.prefix}score\n${this.client.config.prefix}score <member> <type: 'hard' | 'soft'> <reporting department: ex. Library of Code sp-us | Cloud Account Services>:<reason>`;
    this.aliases = ['report'];
    this.subcmds = [Score_Hist, Score_Notify, Score_Pref];
    this.permissions = 0;
    this.guildOnly = false;
    this.enabled = true;
  }

  public async run(message: Message, args: string[]) {
    try {
      let check = false;
      let user: User;
      if (!args[0] || !this.checkCustomPermissions(this.client.util.resolveMember(message.author.id, this.mainGuild), 4)) {
        user = message.author;
        if (!user) return this.error(message.channel, 'Member not found.');
        await this.client.report.createInquiry(user.id, `${user.username} via Discord`, 1);
        check = true;
      } else {
        user = this.client.util.resolveMember(args[0], this.mainGuild)?.user;
        if (!user) {
          const sc = await this.client.db.Score.findOne({ pin: [Number(args[0].split('-')[0]), Number(args[0].split('-')[1]), Number(args[0].split('-')[2])] });
          if (!sc) return this.error(message.channel, 'Member not found.');
          user = this.client.util.resolveMember(sc.userID, this.mainGuild)?.user;
        }
        if (args[1] !== 'soft' && args[1] !== 'hard') return this.error(message.channel, 'Invalid syntax. Report pull type must be "soft" or "hard".');
        if (!user) return this.error(message.channel, 'Member not found.');
        if (message.channel.type !== 0) return this.error(message.channel, 'Hard Inquiries must be initiated in a guild.');
        if (args[1] === 'hard') {
          if (args.length < 3) return this.client.commands.get('help').run(message, [this.name]);
          const name = args.slice(2).join(' ').split(':')[0];
          const reason = args.slice(2).join(' ').split(':')[1];
          const score = await this.client.db.Score.findOne({ userID: user.id });
          if (!score) return this.error(message.channel, 'Score not calculated yet.');
          if (score.locked) return this.error(message.channel, 'The score report you have requested has been locked.');
          await this.client.report.createInquiry(score.userID, name, 0, reason);
        }
      }
      if (!user) return this.error(message.channel, 'Member not found.');
      const score = await this.client.db.Score.findOne({ userID: user.id });
      const inqs = await this.client.db.Inquiry.find({ userID: user.id, type: 0 });
      if (!score) return this.error(message.channel, 'Community Report has not been generated yet.');
      let totalScore = '0';
      let activityScore = '0';
      let moderationScore = '0';
      let roleScore = '0';
      let cloudServicesScore = '0';
      let otherScore = '0';
      let miscScore = '0';

      if (score) {
        if (score.total < 200) totalScore = '---';
        else if (score.total > 800) totalScore = '800';
        else totalScore = `${score.total}`;

        if (score.activity < 10) activityScore = '---';
        else if (score.activity > Math.floor((Math.log1p(getTotalMessageCount(this.client)) * 12))) activityScore = String(Math.floor((Math.log1p(getTotalMessageCount(this.client)) * 12)));
        else activityScore = `${score.activity}`;

        if (score.roles <= 0) roleScore = '---';
        else if (score.roles > 54) roleScore = '54';
        else roleScore = `${score.roles}`;

        moderationScore = `${score.moderation}`;

        if (score.other === 0) otherScore = '---';
        else otherScore = `${score.other}`;

        if (score.staff <= 0) miscScore = '---';
        else miscScore = `${score.staff}`;

        if (score.cloudServices === 0) cloudServicesScore = '---';
        else if (score.cloudServices > 10) cloudServicesScore = '10';
        else cloudServicesScore = `${score.cloudServices}`;
      } // else return this.error(message.channel, 'Community Score has not been calculated yet.');

      const set = [];
      const accounts = await this.client.db.Score.find().lean().exec();
      for (const sc of accounts) {
        if (sc.total < 200) { continue; }
        if (sc.total > 800) { set.push(800); continue; }
        set.push(sc.total);
      }
      const percentile = this.client.util.percentile(set, score.total);
      const embed = new RichEmbed();
      embed.setTitle('Community Report');
      embed.setAuthor(user.username, user.avatarURL);
      embed.setThumbnail(user.avatarURL);
      /* for (const role of member.roles.map((r) => this.mainGuild.roles.get(r)).sort((a, b) => b.position - a.position)) {
        if (role?.color !== 0) {
          embed.setColor(role.color);
          break;
        }
      } */
      let inqAdded = 0;
      if (inqs?.length > 0) {
        let desc = '__**Hard Inquiries**__\n*These inquiries will fall off your report within 2 months, try to keep your hard inquiries to a minimum. If you want to file a dispute, please DM Ramirez.*\n\n';
        inqs.forEach((inq) => {
          const testDate = (new Date(new Date(inq.date).setHours(1460)));
          // eslint-disable-next-line no-useless-escape
          if (testDate > new Date()) {
            desc += `${inq.iid ? `__[${inq.iid}]__\n` : ''}**Department/Service:** ${inq.name.replace(/\*/gmi, '')}\n**Reason:** ${inq.reason}\n**Date:** ${moment(inq.date).format('MMMM Do YYYY, h:mm:ss')}\n**Expires:** ${moment(testDate).calendar()}\n\n`;
            inqAdded++;
          }
        });
        if (inqAdded <= 0) desc = '';
        if (desc.length >= 1900) {
          embed.setDescription('__***Too many Hard Inquiries to show, please see https://report.libraryofcode.org***__');
        } else {
          embed.setDescription(desc);
        }
      }
      let color = '🔴';
      let additionalText = 'POOR';
      embed.setColor('FF0000');
      if (score.total >= 550) { color = '🟠'; additionalText = 'FAIR'; embed.setColor('FFA500'); }
      if (score.total >= 630) { color = '🟡'; additionalText = 'GOOD'; embed.setColor('FFFF00'); }
      if (score.total >= 700) { color = '🟢'; additionalText = 'EXCELLENT'; embed.setColor('66FF66'); }
      if (score.total >= 770) { color = '✨'; additionalText = 'EXCEPTIONAL'; embed.setColor('#99FFFF'); }
      embed.addField('CommScore™ | 200 to 800', score ? `${color} ${totalScore} | ${additionalText} | ${this.client.util.ordinal(Math.round(percentile))} Percentile` : 'N/C', true);
      embed.addField(`Activity | 10 to ${Math.floor(Math.log1p(getTotalMessageCount(this.client)) * 12)}`, activityScore || 'N/C', true);
      embed.addField('Roles | 1 to N/A', roleScore || 'N/C', true);
      embed.addField('Moderation | N/A to 2' || 'N/C', moderationScore, true);
      embed.addField('Cloud Services | N/A to 10+', cloudServicesScore || 'N/C', true);
      embed.addField('Other', otherScore || 'N/C', true);
      embed.addField('Misc', miscScore || 'N/C', true);
      let judgementsStr: string = '';
      const judgements = await this.client.db.Judgement.find({ userID: user.id }).lean().exec();
      if (judgements?.length > 0) {
        for (const judgement of judgements) {
          let severity: string;
          switch (judgement.severity) {
            case 0:
              severity = 'LOW';
              break;
            case 1:
              severity = 'MEDIUM';
              break;
            case 2:
              severity = 'HIGH';
              break;
            default:
              break;
          }
          judgementsStr += `__**Docket #\`${judgement.jid}\`**__\n${judgement.description}\n**Severity:** ${severity}\n**Entered at:** ${moment(judgement.date).format('MMMM Do YYYY, h:mm:ss')}\n**Expiration:** ${judgement.expires ? `${moment(judgement.expires).format('MMMM Do YYYY, h:mm:ss')}` : 'INDEFINITE'}\n\n`;
        }
        if (judgementsStr?.length > 1000) embed.addField('Judgements', '*Too many to list.*');
        else embed.addField('Judgements', judgementsStr);
      }
      if (score.locked) {
        embed.addField('Status', 'Score Report Locked');
      }
      if (score.pin?.length > 0 && message.channel.type === 1) {
        embed.addField('PIN', score.pin.join('-'), true);
      }
      if (score.lastUpdate) {
        embed.setFooter('Report last updated', this.client.user.avatarURL);
        embed.setTimestamp(score.lastUpdate);
      } else {
        embed.setFooter(this.client.user.username, this.client.user.avatarURL);
      }
      // eslint-disable-next-line no-mixed-operators
      if ((args[1] === 'hard' || args[1] === 'soft') && this.checkCustomPermissions(this.client.util.resolveMember(message.author.id, this.mainGuild), 4)) {
        if (score.pin?.length > 0) embed.addField('PIN', score.pin.join('-'), true);

        if (args[1] === 'soft' && !check) {
          let name = '';
          for (const role of this.client.util.resolveMember(message.author.id, this.mainGuild).roles.map((r) => this.mainGuild.roles.get(r)).sort((a, b) => b.position - a.position)) {
            name = `Library of Code sp-us | ${role.name}`;
            break;
          }
          await this.client.report.createInquiry(user.id, name, 1);
        }
      }
      if (args[1] === 'hard' && this.checkCustomPermissions(this.client.util.resolveMember(message.author.id, this.mainGuild), 6)) {
        await message.channel.createMessage({ embed });
        await message.channel.createMessage('***===BEGIN ADDITIONAL INFORMATION===***');
        await this.client.commands.get('score').subcommands.get('hist').run(message, [user.id]);
        await this.client.commands.get('whois').run(message, [user.id]);
        await this.client.commands.get('notes').run(message, [user.id]);
        const whoisMessage = await message.channel.createMessage(`=whois ${user.id} --full`);
        await whoisMessage.delete();
        const modlogsMessage = await message.channel.createMessage(`=modlogs ${user.id}`);
        await modlogsMessage.delete();
        return await message.channel.createMessage('***===END ADDITIONAL INFORMATION===***');
      }
      return message.channel.createMessage({ embed });
    } catch (err) {
      return this.client.util.handleError(err, message, this);
    }
  }
}
