import { Message, TextChannel } from 'eris';
import { apply as Apply } from '.';
import { Client, Command, RichEmbed } from '../class';

import SAA_Approve from './saa_approve';
import SAA_Decline from './saa_decline';

export default class StaffAssistedApplication extends Command {
  public applyCommand: Apply;

  constructor(client: Client) {
    super(client);
    this.name = 'saa';
    this.description = 'Executes a Staff-assisted Application (SAA).';
    this.usage = `${this.client.config.prefix}saa <memberID> <serviceName>`;
    this.permissions = 2;
    this.guildOnly = true;
    this.enabled = true;
    this.subcmds = [SAA_Approve, SAA_Decline];

    this.applyCommand = <Apply> this.client.commands.get('apply');
  }

  public async run(message: Message, args: string[]) {
    try {
      if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);

      const member = this.client.util.resolveMember(args[0], this.mainGuild);
      if (!member) return this.error(message.channel, 'Unable to locate member.');
      const report = await this.client.db.Score.findOne({ userID: member.id }).lean().exec();
      if (!report) return this.error(message.channel, 'Unable to locate Community Report.');
      const staff = await this.client.db.Staff.findOne({ userID: message.author.id }).lean().exec();
      if (!staff) return this.error(message.channel, 'Unable to locate Staff information.');

      const service = this.applyCommand.services.get(args[1]);
      if (!service) return this.error(message.channel, 'Invalid service code.');
      if (service.type !== 'HARD') return this.error(message.channel, 'SAAs cannot be ran for services that do not require a Hard Inquiry or pre-approvals.');
      const preValidationTest = await service.validation(member);
      if (!preValidationTest) return this.error(message.channel, 'This member does not meet pre-validation requirements. A SAA cannot be executed.');

      const loading = await this.loading(message.channel, 'Processing application with EDS. Please hold on a moment.');

      const application = await Apply.apply(this.client, service.url, member.id);

      await (new this.client.db.SAA({
        userID: member.id,
        applicationID: application.id,
        serviceCode: args[1],
        edsToken: application.token,
      })).save();

      await this.client.commands.get('score').run(message, [member.id, 'soft']);

      const edsEmbed = new RichEmbed();
      edsEmbed.setTitle('Decision from EDS');
      if (member) {
        edsEmbed.setAuthor(member.username, member.avatarURL);
      }
      if (application.decision === 'APPROVED') {
        edsEmbed.setColor('#50c878');
      } else if (application.decision === 'DECLINED') {
        edsEmbed.setColor('#fe0000');
      } else if (application.decision === 'PRE-DECLINE') {
        edsEmbed.setColor('#ffa500');
      } else {
        edsEmbed.setColor('#eeeeee');
      }
      let description = `This application was processed by __${application.processedBy}__ on behalf of the vendor, department, or service who operates this application. Please contact the vendor for further information about this application if needed.`;
      if (application.token) description += `\n\n*This document provides detailed information about the decision given by EDS.*: https://eds.libraryofcode.org/dec/${application.token}`;
      edsEmbed.setDescription(description);
      edsEmbed.addField('Status', application.decision, true);
      edsEmbed.addField('User ID', member.id, true);
      edsEmbed.addField('Application ID', application.id, true);
      edsEmbed.setFooter(`${this.client.user.username} via Electronic Decision Service [EDS]`, this.client.user.avatarURL);
      edsEmbed.setTimestamp();
      await message.channel.createMessage({ embed: edsEmbed });

      const embed = new RichEmbed();
      embed.setTitle('Information Panel');
      embed.setDescription('You have been provided with a full report as well as a recommendation from EDS. You should use the information from the Community Report as well as EDS\' recommendation, and other information (such as ?whois, historical report, notes, ect.) to make your decision. If you need assistance, please page a Director.');
      embed.addField('Approve', `Run \`${this.client.config.prefix}saa approve ${application.id}\``);
      embed.addField('Decline', `Run \`${this.client.config.prefix}saa decline ${application.id}\``);
      embed.setFooter(`${this.client.user.username} | Staff-assisted Application via Electronic Decision Service [EDS]`, this.client.user.avatarURL);
      embed.setTimestamp();
      await message.channel.createMessage({ embed });


      const notificationEmbed = new RichEmbed();
      notificationEmbed.setTitle('Staff Assisted Application - Queued');
      // eslint-disable-next-line no-useless-escape
      notificationEmbed.addField('User', `${member.username}#${member.discriminator} | XXX-XX-${report.pin[2]}`);
      notificationEmbed.addField('Decision', 'PROCESSING');
      notificationEmbed.addField('Initiated by', `${message.author.username}, ${staff.pn.slice(0, 2).join(', ')} *on behalf of Library of Code sp-us*`);
      notificationEmbed.addField('Application ID', application.id);
      notificationEmbed.addField('Service Code', args[1]);
      notificationEmbed.setFooter(this.client.user.username, this.client.user.avatarURL);
      notificationEmbed.setTimestamp();

      const log = <TextChannel> this.client.guilds.get(this.client.config.guildID).channels.get('611584771356622849');
      log.createMessage({ embed: notificationEmbed });

      notificationEmbed.setDescription('*A Staff Assisted Application has been queued in your name. If you didn\'t request a SAA to be ran, please contact the Staff Team as soon as possible.\nYou should receive a decision soon, if you do not receive a decision within 72 hours please contact the Staff Team for further information.*');
      const chan = await this.client.getDMChannel(member.id);
      chan.createMessage({ embed: notificationEmbed }).then(() => this.success(message.channel, 'SAA successfully queued.')).catch(() => this.error(message.channel, 'Unable to deliver notification to user.'));

      loading.delete().catch(() => {});
    } catch (err) {
      return this.client.util.handleError(err, message, this);
    }
  }
}
