/* eslint-disable no-bitwise */
import moment from 'moment';
import { Message, Member } from 'eris';
import { Client, Command, RichEmbed } from '../class';
import { whois as emotes } from '../configs/emotes.json';

export default class Whois extends Command {
  constructor(client: Client) {
    super(client);
    this.name = 'whois';
    this.description = 'Provides information on a member.';
    this.usage = 'whois [member]';
    this.permissions = 0;
    this.guildOnly = true;
    this.enabled = true;
  }

  public memberPostNominals(member: Member): string[] | false {
    const arr = [];
    if (member.roles.includes('858049948401401866')) arr.push('RCA');
    if (member.roles.includes('506943223680466955')) arr.push('PRF-C');

    if (arr.length <= 0) return false;
    return arr;
  }

  public async run(message: Message, args: string[]) {
    try {
      let member: Member;
      if (!args[0]) member = message.member;
      else {
        member = this.client.util.resolveMember(args.join(' '), this.mainGuild);
        try {
          if (!member) member = await this.mainGuild.getRESTMember(args[0]);
        } catch {
          return this.error(message.channel, 'Member not found.');
        }
      }

      if (!member) {
        return this.error(message.channel, 'Member not found.');
      }
      const embed = new RichEmbed();
      embed.setThumbnail(member.avatarURL);
      const ackResolve = await this.client.db.Staff.findOne({ userID: member.id }).lean().exec();
      const mpn = this.memberPostNominals(member);
      let title = `${member.user.username}#${member.user.discriminator}`;
      if (!ackResolve && mpn) {
        title += `, ${mpn.join(', ')}`;
      }
      if (ackResolve?.pn?.length > 0) title += `, ${ackResolve.pn.join(', ')}`;
      embed.setAuthor(title, member.user.avatarURL);

      let description = '';
      let titleAndDepartment = '';
      if (ackResolve?.title && ackResolve?.dept) {
        titleAndDepartment += `${emotes.titleAndDepartment} __**${ackResolve.title}**__, __${ackResolve.dept}__\n\n`;
      } else if (ackResolve?.dept) {
        titleAndDepartment += `${emotes.titleAndDepartment} __${ackResolve.dept}__\n\n`;
      }
      if (titleAndDepartment.length > 0) description += titleAndDepartment;
      if (ackResolve?.emailAddress) {
        description += `${emotes.email} ${ackResolve.emailAddress}\n`;
      }
      const pager = await this.client.db.PagerNumber.findOne({ individualAssignID: member.user.id }).lean().exec();
      if (pager?.num) {
        description += `📟 ${pager.num}\n`;
      }
      if (ackResolve?.extension) {
        description += `☎️ ${ackResolve.extension}\n`;
      }
      const memberProfile = await this.client.db.Member.findOne({ userID: member.id }).lean().exec();
      if (memberProfile?.additional?.gitlab) {
        description += `${emotes.gitlab} ${memberProfile?.additional.gitlab}\n`;
      }
      if (memberProfile?.additional?.github) {
        description += `${emotes.github} ${memberProfile?.additional.github}\n`;
      }
      if (memberProfile?.additional?.bio) {
        description += `${emotes.bio} *${memberProfile?.additional.bio}*\n`;
      }
      description += `\n<@${member.id}>`;
      embed.setDescription(description);

      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;
        }
      }
      embed.addField('Status', member.status === 'dnd' ? 'Do Not Disturb' : this.client.util.capsFirstLetter(member.status) || 'Offline', true);
      embed.addField('Joined At', `${moment(new Date(member.joinedAt)).format('dddd, MMMM Do YYYY, h:mm:ss A')} ET`, true);
      embed.addField('Created At', `${moment(new Date(member.user.createdAt)).format('dddd, MMMM Do YYYY, h:mm:ss A')} ET`, true);
      const score = await this.client.db.Score.findOne({ userID: member.id }).lean().exec();
      if (score) {
        await this.client.report.createInquiry(member.id, 'Library of Code sp-us | Bureau of Community Reports', 1);
        let totalScore = '0';
        if (score.total < 200) totalScore = '---';
        else if (score.total > 800) totalScore = '800';
        else totalScore = `${score.total}`;
        embed.addField('CommScore™', totalScore, true);
      } else embed.addField('CommScore™', 'N/C', true);

      if (member.roles.length > 0) {
        embed.addField(`Roles [${member.roles.length}]`, member.roles.map((r) => this.mainGuild.roles.get(r)).sort((a, b) => b.position - a.position).map((r) => `<@&${r.id}>`).join(', '));
      }

      const flags: string[] = [];
      if (member.user.publicFlags) {
        if ((member.user.publicFlags & (1 << 12)) === 1 << 12) flags.push('<:System:768370601265201152>');
        if ((member.user.publicFlags & (1 << 0)) === 1 << 0) flags.push('<:DiscordStaff:768370601882025985>');
        if ((member.user.publicFlags & (1 << 1)) === 1 << 1) flags.push('<:Partnered:768370601395879936>');
        if ((member.user.publicFlags & (1 << 3)) === 1 << 3) flags.push('<:BugHunter:768370601105555467>');
        if ((member.user.publicFlags & (1 << 14)) === 1 << 14) flags.push('<:BugHunter:768370601105555467>');
        if ((member.user.publicFlags & (1 << 2)) === 1 << 2) flags.push('<:HypeSquadEvents:768370600745762846>');
        if ((member.user.publicFlags & (1 << 6)) === 1 << 6) flags.push('<:HypeSquadBravery:768370601328640011> ');
        if ((member.user.publicFlags & (1 << 7)) === 1 << 7) flags.push('<:HypeSquadBrilliance:768370600842362900>');
        if ((member.user.publicFlags & (1 << 8)) === 1 << 8) flags.push('<:HypeSquadBalance:768370599584071751> ');
        if ((member.user.publicFlags & (1 << 9)) === 1 << 9) flags.push('<:EarlySupporter:768370601873768468>');
        if ((member.user.publicFlags & (1 << 16)) === 1 << 16) flags.push('<:VerifiedBot:768370599252197396>');
        if ((member.user.publicFlags & (1 << 17)) === 1 << 17) flags.push('<:VerifiedBotDeveloper:768370601701933077>');
      }
      if (flags.length > 0) embed.addField('Flags', flags.join(' '));

      const permissions: string[] = [];
      const serverAcknowledgements: string[] = [];
      const bit = Number(member.permissions.allow);
      if (this.mainGuild.ownerID === member.id) serverAcknowledgements.push('Server Owner');
      if (bit & 8) { permissions.push('Administrator'); serverAcknowledgements.push('Server Admin'); }
      if (bit & 32) { permissions.push('Manage Server'); serverAcknowledgements.push('Server Manager'); }
      if (bit & 16) permissions.push('Manage Channels');
      if (bit & 268435456) permissions.push('Manage Roles');
      if (bit & 8192) { permissions.push('Manage Messages'); serverAcknowledgements.push('Server Moderator'); }
      if (bit & 134217728) permissions.push('Manage Nicknames');
      if (bit & 1073741824) permissions.push('Manage Emojis');
      if (bit & 4) permissions.push('Ban Members');
      if (bit & 2) permissions.push('Kick Members');


      const account = await this.client.db.Member.findOne({ userID: member.id }).lean().exec();
      if (account?.additional?.langs?.length > 0) {
        const langs: string[] = [];
        for (const lang of account.additional.langs.sort((a, b) => a.localeCompare(b))) {
          switch (lang) {
            case 'asm':
              langs.push('<:AssemblyLanguage:703448714248716442> Assembly Language');
              break;
            case 'cfam':
              langs.push('<:clang:553684262193332278> C/C++');
              break;
            case 'csharp':
              langs.push('<:csharp:553684277280112660> C#');
              break;
            case 'go':
              langs.push('<:Go:703449475405971466> Go');
              break;
            case 'java':
              langs.push('<:Java:703449725181100135> Java');
              break;
            case 'js':
              langs.push('<:JavaScriptECMA:703449987916496946> JavaScript');
              break;
            case 'kt':
              langs.push('<:Kotlin:703450201838321684> Kotlin');
              break;
            case 'py':
              langs.push('<:python:553682965482176513> Python');
              break;
            case 'rb':
              langs.push('<:ruby:604812470451699712> Ruby');
              break;
            case 'rs':
              langs.push('<:Rust:703450901960196206> Rust');
              break;
            case 'swift':
              langs.push('<:Swift:703451096093294672> Swift');
              break;
            case 'ts':
              langs.push('<:TypeScript:703451285789343774> TypeScript');
              break;
            default:
              break;
          }
        }
        embed.addField('Known Languages', langs.join(', '));
      }
      if (account?.additional?.operatingSystems?.length > 0) {
        const operatingSystems: string[] = [];
        for (const os of account.additional.operatingSystems.sort((a, b) => a.localeCompare(b))) {
          switch (os) {
            case 'arch':
              operatingSystems.push('<:arch:707694976523304960> Arch');
              break;
            case 'deb':
              operatingSystems.push('<:debian:707695042617147589> Debian');
              break;
            case 'cent':
              operatingSystems.push('<:centos:707702165816213525> CentOS');
              break;
            case 'fedora':
              operatingSystems.push('<:fedora:707695073151680543> Fedora');
              break;
            case 'manjaro':
              operatingSystems.push('<:manjaro:707701473680556062> Manjaro');
              break;
            case 'mdarwin':
              operatingSystems.push('<:mac:707695427754917919> macOS');
              break;
            case 'redhat':
              operatingSystems.push('<:redhat:707695102159749271> RedHat Enterprise Linux');
              break;
            case 'ubuntu':
              operatingSystems.push('<:ubuntu:707695136888586300> Ubuntu');
              break;
            case 'win':
              operatingSystems.push('<:windows10:707695160259248208> Windows');
              break;
            default:
              break;
          }
        }
        embed.addField('Used Operating Systems', operatingSystems.join(', '));
      }
      if (permissions.length > 0) {
        embed.addField('Permissions', permissions.join(', '));
      }
      if (serverAcknowledgements.length > 0) {
        embed.addField('Acknowledgements', serverAcknowledgements[0]);
      }
      if (ackResolve?.additionalRoles?.length > 0) {
        embed.addField('Additional Acknowledgements', ackResolve.additionalRoles.join(', '));
      }
      embed.setFooter(this.client.user.username, this.client.user.avatarURL);
      embed.setTimestamp();
      return message.channel.createMessage({ embed });
    } catch (err) {
      return this.client.util.handleError(err, message, this);
    }
  }
}
