/* eslint-disable no-plusplus */
/* eslint-disable no-continue */
/* eslint-disable one-var-declaration-per-line */
/* eslint-disable no-await-in-loop */
import axios from 'axios';
import { Message, TextChannel } from 'eris';
import { Client } from '../class';

interface CSResponse {
  found: boolean,
  tier: number,
  totalReferrals?: number,
  createdAt?: Date,
  warns?: Date[],
  locks?: Date[],
  deletes?: Date[],
}

let interval: NodeJS.Timeout;

export function getTotalMessageCount(client: Client): number {
  const projectChannels: TextChannel[] = [];
  for (const c of client.guilds.get(client.config.guildID).channels.filter((ch) => ch.type === 0)) {
    const chan = <TextChannel> c;
    if (chan.parentID !== '701591772186411108') continue;
    projectChannels.push(chan);
  }
  return (projectChannels.length * 200) + 2200 + 300 + 100 + 200;
}

export default async function calculateScore(client: Client): Promise<NodeJS.Timeout> {
  const start = async () => {
    const { members } = client.guilds.get(client.config.guildID);

    const general = await (<TextChannel> client.guilds.get(client.config.guildID).channels.get('485680288123584525')).getMessages(2200);
    const programmingSupport = await (<TextChannel> client.guilds.get(client.config.guildID).channels.get('506970598631538708')).getMessages(300);
    const programmingSupport2 = await (<TextChannel> client.guilds.get(client.config.guildID).channels.get('554892820553531422')).getMessages(100);
    const cloudSupport = await (<TextChannel> client.guilds.get(client.config.guildID).channels.get('546457788184789013')).getMessages(200);

    const projectChannels: TextChannel[] = [];
    for (const c of client.guilds.get(client.config.guildID).channels.filter((ch) => ch.type === 0)) {
      const chan = <TextChannel> c;
      if (chan.parentID !== '701591772186411108') continue;
      projectChannels.push(chan);
    }
    const projectMessages: Message<TextChannel>[] = [];
    for (const chan of projectChannels) {
      const msg = await chan.getMessages(200);
      projectMessages.push(...msg);
    }
    for (const member of members.values()) {
      if (member.bot) continue;
      let score = await client.db.Score.findOne({ userID: member.user.id });
      if (!score) {
        const data: {
          userID: string,
          total: number,
          activity: number,
          roles: number,
          moderation: number,
          cloudServices: number,
          other: number,
          staff: boolean,
          locked: boolean,
          notify: boolean,
          lastUpdated: Date,
          pin: number[],
        } = {
          userID: member.user.id,
          total: 0,
          activity: 0,
          roles: 0,
          moderation: 0,
          cloudServices: 0,
          other: 0,
          staff: false,
          locked: false,
          notify: false,
          lastUpdated: new Date(),
          pin: [client.util.randomNumber(100, 999), client.util.randomNumber(10, 99), client.util.randomNumber(1000, 9999)],
        };
        score = await (new client.db.Score(data)).save();
        client.util.signale.debug(`SCORE INIT - ${member.username}`);
      }

      // eslint-disable-next-line prefer-const
      // eslint-disable-next-line one-var-declaration-per-line
      // eslint-disable-next-line one-var
      let total = 0, activity = 0, roles = 0, moderation = 0, cloudServices = 0, other = 0, staff = 0;
      cloudServices = 0;

      roles = Math.floor(member.roles.length * 0.50);
      if (roles > 54) roles = 54;

      const moderations = await client.db.Moderation.find({ userID: member.user.id });
      let activeMods = 0;
      for (const mod of moderations) {
        if (mod.type === 1 || mod.type === 4) continue;
        const testDate = (new Date(new Date(mod.date).setHours(2190)));
        if (testDate > new Date()) { moderation -= 15; activeMods++; }
      }
      if (activeMods <= 0) moderation = 2;

      let messageCountTotal = 0;
      const allMessagesArray = [...general, ...programmingSupport, ...programmingSupport2, ...cloudSupport, ...projectMessages];

      for (const msg of allMessagesArray.filter((m) => m.member?.id === member.id)) {
        if (!msg.content) continue;
        if (msg.content.length <= 5) continue;
        // eslint-disable-next-line no-plusplus
        messageCountTotal++;
      }

      const activityTotal = messageCountTotal;
      activity = Math.floor(Math.log1p(activityTotal) * 12);
      if (activity > (Math.log1p(getTotalMessageCount(client)) * 12)) activity = Math.floor((Math.log1p(getTotalMessageCount(client)) * 12));
      if (member.roles.includes('446104438969466890') || member.roles.includes('701481967149121627')) staff = 20;

      const response = <CSResponse> (await axios.get(`https://api.cloud.libraryofcode.org/wh/score?id=${member.user.id}&authorization=${client.config.internalKey}`)).data;
      if (response.found === true) {
        let negatives = 0;
        let positives = 0;
        if (response.createdAt) {
          const csCreatedTestDate = (new Date(new Date(response.createdAt).setHours(730)));
          if (csCreatedTestDate > new Date()) {
            negatives -= 10;
          }
        }
        let warns = 0;
        for (const warn of response.warns) {
          const date = (new Date(new Date(warn).setHours(730)));
          if (date > new Date()) { negatives -= 2; warns++; }
        }
        if (warns <= 0) positives += 2;
        if (response.warns.length === 0) positives += 3;

        let locks = 0;
        for (const lock of response.locks) {
          const date = (new Date(new Date(lock).setHours(1460)));
          if (date > new Date()) { negatives -= 5; locks++; }
        }
        if (locks <= 0) positives += 3;
        if (response.locks.length === 0) positives += 7;

        if (response.deletes.length > 0) {
          for (const del of response.deletes) {
            const date = (new Date(new Date(del).setHours(3650)));
            if (date > new Date()) negatives -= 20;
          }
        }
        positives += Math.floor(response.totalReferrals * 1.17);
        if (response.tier === 2) positives += 2;
        else if (response.tier === 3) positives += 3;

        if (negatives < 0) cloudServices = Math.floor((negatives * 1.2) + (positives * 0.06));
        else cloudServices = Math.floor(positives * 0.61);
      }

      const inquiries = await client.db.Inquiry.find({ userID: member.user.id, type: 0 }).lean().exec();
      const judgements = await client.db.Judgement.find({ userID: member.user.id }).lean().exec();

      if (inquiries?.length > 0) {
        for (const inq of inquiries) {
          const testDate = (new Date(new Date(inq.date).setHours(1460)));
          if (testDate > new Date()) other -= 1.65;
        }
        other = Math.floor(other * 1.15);
      }

      if (judgements?.length > 0) {
        for (const judgement of judgements) {
          switch (judgement.severity) {
            default:
              break;
            case 0:
              other -= 5;
              break;
            case 1:
              other -= 10;
              break;
            case 2:
              other -= 20;
              break;
          }
        }
      }

      const discordAccountCreatedAtTestDate = (new Date(new Date(new Date(member.user.createdAt)).setHours(730)));
      if (discordAccountCreatedAtTestDate > new Date()) {
        other -= 10;
      }

      const joinedAtTestDate = (new Date(new Date(new Date(member.joinedAt)).setHours(420)));
      if (joinedAtTestDate > new Date()) {
        other -= 30;
      }

      total = Math.floor(((total + activity + roles + moderation + cloudServices + staff + other) * 5.13) * 1.87);

      client.queue.updateScore(score, total, activity, roles, moderation, cloudServices, other, staff);
    }
  };
  await start();
  interval = setInterval(async () => {
    await start();
  }, 1800000);
  return interval;
}
