/* eslint-disable no-continue */
/* eslint-disable no-await-in-loop */
import { Member, TextableChannel } from 'eris';
import { Client } from '../class';

let interval: NodeJS.Timeout;

async function setupDepartmentCodes(client: Client): Promise<void> {
  const directorPagers = await client.db.PagerNumber.findOne({ num: '00' }).lean().exec();
  const supervisorPagers = await client.db.PagerNumber.findOne({ num: '01' }).lean().exec();
  const technicianPagers = await client.db.PagerNumber.findOne({ num: '10' }).lean().exec();
  const moderatorPagers = await client.db.PagerNumber.findOne({ num: '20' }).lean().exec();
  const coreTeamPagers = await client.db.PagerNumber.findOne({ num: '21' }).lean().exec();
  const associatePagers = await client.db.PagerNumber.findOne({ num: '22' }).lean().exec();

  if (!directorPagers) {
    const setup = new client.db.PagerNumber({
      num: '00',
      individualAssignID: '',
      emailAddresses: [],
      discordIDs: [],
    });
    await setup.save();
  }
  if (!supervisorPagers) {
    const setup = new client.db.PagerNumber({
      num: '01',
      individualAssignID: '',
      emailAddresses: [],
      discordIDs: [],
    });
    await setup.save();
  }
  if (!technicianPagers) {
    const setup = new client.db.PagerNumber({
      num: '10',
      individualAssignID: '',
      emailAddresses: [],
      discordIDs: [],
    });
    setup.save();
  }
  if (!moderatorPagers) {
    const setup = new client.db.PagerNumber({
      num: '20',
      individualAssignID: '',
      emailAddresses: [],
      discordIDs: [],
    });
    await setup.save();
  }
  if (!coreTeamPagers) {
    const setup = new client.db.PagerNumber({
      num: '21',
      individualAssignID: '',
      emailAddresses: [],
      discordIDs: [],
    });
    await setup.save();
  }
  if (!associatePagers) {
    const setup = new client.db.PagerNumber({
      num: '22',
      individualAssignID: '',
      emailAddresses: [],
      discordIDs: [],
    });
    await setup.save();
  }
}

function logNewPager(client: Client, num: string, member: Member): void {
  client.util.signale.log(`Pager Number '${num}' created for '${member.user.username}#${member.user.discriminator}'.`);
  const channel = <TextableChannel>client.guilds.get(client.config.guildID).channels.get('722636436716781619');
  channel.createMessage(`__**'${member.user.username}#${member.user.discriminator}' assigned to pager number '${num}'.**__`);
}

export default async function departmentPager(client: Client): Promise<NodeJS.Timeout> {
  setupDepartmentCodes(client);
  // eslint-disable-next-line no-shadow
  async function start(client: Client) {
    async function resolveStaffInformation(id: string) {
      return client.db.Staff.findOne({ userID: id }); // acknowledgements.find((m) => m.id === id);
    }
    await client.guilds.get(client.config.guildID).fetchAllMembers();
    const members = client.guilds.get(client.config.guildID).members.map((m) => m);

    for (const member of members) {
      const pager = await client.db.PagerNumber.findOne({ individualAssignID: member.id }).lean().exec();
      if (!pager) continue;
      if (pager.num.startsWith('00') && !member.roles.includes('662163685439045632')) {
        await client.db.PagerNumber.deleteOne({ num: pager.num });
        await client.util.authClient.deleteUser({ id: member.id });
        client.util.signale.log(`Pager Number '${pager.num}' has been deleted.`);
        await client.util.removeUserFromMailingList(pager.emailAddresses[0], 'all-staff');
      }
      if (pager.num.startsWith('01') && !member.roles.includes('701454855952138300')) {
        await client.db.PagerNumber.deleteOne({ num: pager.num });
        await client.util.authClient.deleteUser({ id: member.id });
        client.util.signale.log(`Pager Number '${pager.num}' has been deleted.`);
        await client.util.removeUserFromMailingList(pager.emailAddresses[0], 'all-staff');
      }
      if (pager.num.startsWith('10') && !member.roles.includes('701454780828221450')) {
        await client.db.PagerNumber.deleteOne({ num: pager.num });
        await client.util.authClient.deleteUser({ id: member.id });
        client.util.signale.log(`Pager Number '${pager.num}' has been deleted.`);
        await client.util.removeUserFromMailingList(pager.emailAddresses[0], 'all-staff');
      }
      if (pager.num.startsWith('20') && !member.roles.includes('455972169449734144')) {
        await client.db.PagerNumber.deleteOne({ num: pager.num });
        await client.util.authClient.deleteUser({ id: member.id });
        client.util.signale.log(`Pager Number '${pager.num}' has been deleted.`);
        await client.util.removeUserFromMailingList(pager.emailAddresses[0], 'all-staff');
      }
      if (pager.num.startsWith('21') && !member.roles.includes('453689940140883988')) {
        await client.db.PagerNumber.deleteOne({ num: pager.num });
        await client.util.authClient.deleteUser({ id: member.id });
        client.util.signale.log(`Pager Number '${pager.num}' has been deleted.`);
        await client.util.removeUserFromMailingList(pager.emailAddresses[0], 'all-staff');
      }
      if (pager.num.startsWith('22') && !member.roles.includes('701481967149121627')) {
        await client.db.PagerNumber.deleteOne({ num: pager.num });
        await client.util.authClient.deleteUser({ id: member.id });
        client.util.signale.log(`Pager Number '${pager.num}' has been deleted.`);
        await client.util.removeUserFromMailingList(pager.emailAddresses[0], 'all-staff');
      }
    }

    for (const member of members) {
      let pager = await client.db.PagerNumber.findOne({ individualAssignID: member.id }).lean().exec();

      // ADD TO ALL STAFF MAILING LIST
      if ((member.roles.includes('453689940140883988') || member.roles.includes('701481967149121627')) && !pager) {
        const acknowledgement = await resolveStaffInformation(member.id);
        await client.util.addUserToMailingList(acknowledgement.emailAddress, 'all-staff');
      }
      // Directors
      if (!pager && member.roles.includes('662163685439045632')) {
        let randomPagerNumber: string;
        let status = true;
        // eslint-disable-next-line no-constant-condition
        while (status) {
          randomPagerNumber = `00${String(Math.floor(Math.random() * 9) + 1)}`;
          const check = await client.db.PagerNumber.findOne({ num: randomPagerNumber });
          if (check) status = false;
          if (check?.num !== randomPagerNumber) status = false;
        }
        const acknowledgement = await resolveStaffInformation(member.id);
        if (!acknowledgement || !acknowledgement.emailAddress) continue;
        const newNumber = new client.db.PagerNumber({
          num: randomPagerNumber,
          individualAssignID: member.id,
          emailAddresses: [acknowledgement.emailAddress],
          discordIDs: [member.id],
        });
        if (await client.db.PagerNumber.findOne({ num: randomPagerNumber })) continue;
        pager = await newNumber.save();
        await client.util.authClient.createUser({
          email: acknowledgement.emailAddress,
          name: member.username,
          user_id: member.id,
          connection: 'Staff-Database',
          email_verified: true,
          app_metadata: {
            boardOfDirectors: true,
          },
          picture: member.avatarURL,
          password: client.config.defaultAccountPassword,
        });
        const passwordTicket = await client.util.authClient.createPasswordChangeTicket({
          email: acknowledgement.emailAddress,
          connection_id: 'con_T3ELEx2reigKMSlP',
        });
        logNewPager(client, randomPagerNumber, member);
        client.getDMChannel(member.id).then((chan) => {
          chan.createMessage(`__**Pager Number Creation**__\nYour individual pager number has been automatically created. Your number (PN) is ${randomPagerNumber}.`);
          chan.createMessage(`__**Library of Code sp-us | Identity & Account Management**__\n__Reset Password__\n\nPlease click on the link below to change your IAM password.\n${passwordTicket.ticket}`);
        });
      } else if (!pager && member.roles.includes('701454855952138300')) {
        // Supervisors
        let randomPagerNumber: string;
        let status = true;
        // eslint-disable-next-line no-constant-condition
        while (status) {
          randomPagerNumber = `01${String(Math.floor(Math.random() * 9) + 1)}`;
          const check = await client.db.PagerNumber.findOne({ num: randomPagerNumber });
          if (check) status = false;
          if (check?.num !== randomPagerNumber) status = false;
        }
        const acknowledgement = await resolveStaffInformation(member.id);
        if (!acknowledgement || !acknowledgement.emailAddress) continue;
        const newNumber = new client.db.PagerNumber({
          num: randomPagerNumber,
          individualAssignID: member.id,
          emailAddresses: [acknowledgement.emailAddress],
          discordIDs: [member.id],
        });
        if (await client.db.PagerNumber.findOne({ num: randomPagerNumber })) continue;
        pager = await newNumber.save();
        await client.util.authClient.createUser({
          email: acknowledgement.emailAddress,
          name: member.username,
          user_id: member.id,
          connection: 'Staff-Database',
          email_verified: true,
          app_metadata: {
            supervisor: true,
          },
          picture: member.avatarURL,
          password: client.config.defaultAccountPassword,
        });
        const passwordTicket = await client.util.authClient.createPasswordChangeTicket({
          email: acknowledgement.emailAddress,
          connection_id: 'con_T3ELEx2reigKMSlP',
        });
        logNewPager(client, randomPagerNumber, member);
        client.getDMChannel(member.id).then((chan) => {
          chan.createMessage(`__**Pager Number Creation**__\nYour individual pager number has been automatically created. Your number (PN) is ${randomPagerNumber}.`);
          chan.createMessage(`__**Library of Code sp-us | Identity & Account Management**__\n__Reset Password__\n\nPlease click on the link below to change your IAM password.\n${passwordTicket.ticket}`);
        });
      } else if (!pager && member.roles.includes('701454780828221450')) {
        // Technicians
        let randomPagerNumber: string;
        let status = true;
        // eslint-disable-next-line no-constant-condition
        while (status) {
          randomPagerNumber = `10${String(Math.floor(Math.random() * 99) + 1)}`;
          if (randomPagerNumber.length === 3) randomPagerNumber = `${randomPagerNumber}0`;
          const check = await client.db.PagerNumber.findOne({ num: randomPagerNumber });
          if (check) status = false;
          if (check?.num !== randomPagerNumber) status = false;
        }
        const acknowledgement = await resolveStaffInformation(member.id);
        if (!acknowledgement || !acknowledgement.emailAddress) continue;
        const newNumber = new client.db.PagerNumber({
          num: randomPagerNumber,
          individualAssignID: member.id,
          emailAddresses: [acknowledgement.emailAddress],
          discordIDs: [member.id],
        });
        if (await client.db.PagerNumber.findOne({ num: randomPagerNumber })) continue;
        pager = await newNumber.save();
        await client.util.authClient.createUser({
          email: acknowledgement.emailAddress,
          name: member.username,
          user_id: member.id,
          connection: 'Staff-Database',
          email_verified: true,
          app_metadata: {
            technician: true,
          },
          picture: member.avatarURL,
          password: client.config.defaultAccountPassword,
        });
        const passwordTicket = await client.util.authClient.createPasswordChangeTicket({
          email: acknowledgement.emailAddress,
          connection_id: 'con_T3ELEx2reigKMSlP',
        });
        logNewPager(client, randomPagerNumber, member);
        client.getDMChannel(member.id).then((chan) => {
          chan.createMessage(`__**Pager Number Creation**__\nYour individual pager number has been automatically created. Your number (PN) is ${randomPagerNumber}.`);
          chan.createMessage(`__**Library of Code sp-us | Identity & Account Management**__\n__Reset Password__\n\nPlease click on the link below to change your IAM password.\n${passwordTicket.ticket}`);
        });
      } else if (!pager && member.roles.includes('455972169449734144')) {
        // Moderators
        let randomPagerNumber: string;
        let status = true;
        // eslint-disable-next-line no-constant-condition
        while (status) {
          randomPagerNumber = `20${String(Math.floor(Math.random() * 99) + 1)}`;
          if (randomPagerNumber.length === 3) randomPagerNumber = `${randomPagerNumber}0`;
          const check = await client.db.PagerNumber.findOne({ num: randomPagerNumber });
          if (check) status = false;
          if (check?.num !== randomPagerNumber) status = false;
        }
        const acknowledgement = await resolveStaffInformation(member.id);
        if (!acknowledgement || !acknowledgement.emailAddress) continue;
        const newNumber = new client.db.PagerNumber({
          num: randomPagerNumber,
          individualAssignID: member.id,
          emailAddresses: [acknowledgement.emailAddress],
          discordIDs: [member.id],
        });
        if (await client.db.PagerNumber.findOne({ num: randomPagerNumber })) continue;
        pager = await newNumber.save();
        await client.util.authClient.createUser({
          email: acknowledgement.emailAddress,
          name: member.username,
          user_id: member.id,
          connection: 'Staff-Database',
          email_verified: true,
          app_metadata: {
            moderator: true,
          },
          picture: member.avatarURL,
          password: client.config.defaultAccountPassword,
        });
        const passwordTicket = await client.util.authClient.createPasswordChangeTicket({
          email: acknowledgement.emailAddress,
          connection_id: 'con_T3ELEx2reigKMSlP',
        });
        logNewPager(client, randomPagerNumber, member);
        client.getDMChannel(member.id).then((chan) => {
          chan.createMessage(`__**Pager Number Creation**__\nYour individual pager number has been automatically created. Your number (PN) is ${randomPagerNumber}.`);
          chan.createMessage(`__**Library of Code sp-us | Identity & Account Management**__\n__Reset Password__\n\nPlease click on the link below to change your IAM password.\n${passwordTicket.ticket}`);
        });
      } else if (!pager && member.roles.includes('453689940140883988')) {
        // Core Team
        let randomPagerNumber: string;
        let status = true;
        // eslint-disable-next-line no-constant-condition
        while (status) {
          randomPagerNumber = `21${String(Math.floor(Math.random() * 999) + 1)}`;
          if (randomPagerNumber.length === 4) randomPagerNumber = `${randomPagerNumber}0`;
          const check = await client.db.PagerNumber.findOne({ num: randomPagerNumber });
          if (check) status = false;
          if (check?.num !== randomPagerNumber) status = false;
        }
        const acknowledgement = await resolveStaffInformation(member.id);
        if (!acknowledgement || !acknowledgement.emailAddress) continue;
        const newNumber = new client.db.PagerNumber({
          num: randomPagerNumber,
          individualAssignID: member.id,
          emailAddresses: [acknowledgement.emailAddress],
          discordIDs: [member.id],
        });
        if (await client.db.PagerNumber.findOne({ num: randomPagerNumber })) continue;
        pager = await newNumber.save();
        await client.util.authClient.createUser({
          email: acknowledgement.emailAddress,
          name: member.username,
          user_id: member.id,
          connection: 'Staff-Database',
          email_verified: true,
          app_metadata: {
            coreTeam: true,
          },
          picture: member.avatarURL,
          password: client.config.defaultAccountPassword,
        });
        const passwordTicket = await client.util.authClient.createPasswordChangeTicket({
          email: acknowledgement.emailAddress,
          connection_id: 'con_T3ELEx2reigKMSlP',
        });
        logNewPager(client, randomPagerNumber, member);
        client.getDMChannel(member.id).then((chan) => {
          chan.createMessage(`__**Pager Number Creation**__\nYour individual pager number has been automatically created. Your number (PN) is ${randomPagerNumber}.`);
          chan.createMessage(`__**Library of Code sp-us | Identity & Account Management**__\n__Reset Password__\n\nPlease click on the link below to change your IAM password.\n${passwordTicket.ticket}`);
        });
      } else if (!pager && member.roles.includes('701481967149121627')) {
        // Associates
        let randomPagerNumber: string;
        let status = true;
        // eslint-disable-next-line no-constant-condition
        while (status) {
          randomPagerNumber = `22${String(Math.floor(Math.random() * 999) + 1)}`;
          if (randomPagerNumber.length === 4) randomPagerNumber = `${randomPagerNumber}0`;
          const check = await client.db.PagerNumber.findOne({ num: randomPagerNumber });
          if (check) status = false;
          if (check?.num !== randomPagerNumber) status = false;
        }
        const acknowledgement = await resolveStaffInformation(member.id);
        if (!acknowledgement || !acknowledgement.emailAddress) continue;
        const newNumber = new client.db.PagerNumber({
          num: randomPagerNumber,
          individualAssignID: member.id,
          emailAddresses: [acknowledgement.emailAddress],
          discordIDs: [member.id],
        });
        if (await client.db.PagerNumber.findOne({ num: randomPagerNumber })) continue;
        pager = await newNumber.save();
        await client.util.authClient.createUser({
          email: acknowledgement.emailAddress,
          name: member.username,
          user_id: member.id,
          connection: 'Staff-Database',
          email_verified: true,
          app_metadata: {
            associate: true,
          },
          picture: member.avatarURL,
          password: client.config.defaultAccountPassword,
        });
        const passwordTicket = await client.util.authClient.createPasswordChangeTicket({
          email: acknowledgement.emailAddress,
          connection_id: 'con_T3ELEx2reigKMSlP',
        });
        logNewPager(client, randomPagerNumber, member);
        client.getDMChannel(member.id).then((chan) => {
          chan.createMessage(`__**Pager Number Creation**__\nYour individual pager number has been automatically created. Your number (PN) is ${randomPagerNumber}.`);
          chan.createMessage(`__**Library of Code sp-us | Identity & Account Management**__\n__Reset Password__\n\nPlease click on the link below to change your IAM password.\n${passwordTicket.ticket}`);
        });
      }
    }

    // Associates
    const associatePagers = await client.db.PagerNumber.findOne({ num: '22' });
    for (const member of members) {
      if (member.roles.includes('701481967149121627') && !associatePagers.discordIDs.includes(member.id)) {
        await associatePagers.updateOne({ $addToSet: { discordIDs: member.id } });
        const acknowledgement = await resolveStaffInformation(member.id);
        if (acknowledgement?.emailAddress) await associatePagers.updateOne({ $addToSet: { emailAddresses: acknowledgement.emailAddress } });
      }
      if (!member.roles.includes('701481967149121627') && associatePagers.discordIDs.includes(member.id)) {
        await associatePagers.updateOne({ $pull: { discordIDs: member.id } });
        const acknowledgement = await resolveStaffInformation(member.id);
        if (acknowledgement?.emailAddress) await associatePagers.updateOne({ $pull: { emailAddresses: acknowledgement.emailAddress } });
      }
    }
    // Core Team
    const coreTeamPagers = await client.db.PagerNumber.findOne({ num: '21' });
    for (const member of members) {
      if (member.roles.includes('453689940140883988') && !coreTeamPagers.discordIDs.includes(member.id)) {
        await coreTeamPagers.updateOne({ $addToSet: { discordIDs: member.id } });
        const acknowledgement = await resolveStaffInformation(member.id);
        if (acknowledgement?.emailAddress) await coreTeamPagers.updateOne({ $addToSet: { emailAddresses: acknowledgement.emailAddress } });
      }
      if (!member.roles.includes('453689940140883988') && coreTeamPagers.discordIDs.includes(member.id)) {
        await coreTeamPagers.updateOne({ $pull: { discordIDs: member.id } });
        const acknowledgement = await resolveStaffInformation(member.id);
        if (acknowledgement?.emailAddress) await coreTeamPagers.updateOne({ $pull: { emailAddresses: acknowledgement.emailAddress } });
      }
    }
    // Moderator
    const moderatorPagers = await client.db.PagerNumber.findOne({ num: '20' });
    for (const member of members) {
      if (member.roles.includes('455972169449734144') && !moderatorPagers.discordIDs.includes(member.id)) {
        await moderatorPagers.updateOne({ $addToSet: { discordIDs: member.id } });
        const acknowledgement = await resolveStaffInformation(member.id);
        if (acknowledgement?.emailAddress) await moderatorPagers.updateOne({ $addToSet: { emailAddresses: acknowledgement.emailAddress } });
      }
      if (!member.roles.includes('455972169449734144') && moderatorPagers.discordIDs.includes(member.id)) {
        await moderatorPagers.updateOne({ $pull: { discordIDs: member.id } });
        const acknowledgement = await resolveStaffInformation(member.id);
        if (acknowledgement?.emailAddress) await moderatorPagers.updateOne({ $pull: { emailAddresses: acknowledgement.emailAddress } });
      }
    }
    // Technician
    const technicianPagers = await client.db.PagerNumber.findOne({ num: '10' });
    for (const member of members) {
      if (member.roles.includes('701454780828221450') && !technicianPagers.discordIDs.includes(member.id)) {
        await technicianPagers.updateOne({ $addToSet: { discordIDs: member.id } });
        const acknowledgement = await resolveStaffInformation(member.id);
        if (acknowledgement?.emailAddress) await technicianPagers.updateOne({ $addToSet: { emailAddresses: acknowledgement.emailAddress } });
      }
      if (!member.roles.includes('701454780828221450') && technicianPagers.discordIDs.includes(member.id)) {
        await technicianPagers.updateOne({ $pull: { discordIDs: member.id } });
        const acknowledgement = await resolveStaffInformation(member.id);
        if (acknowledgement?.emailAddress) await technicianPagers.updateOne({ $pull: { emailAddresses: acknowledgement.emailAddress } });
      }
    }
    // Supervisor
    const supervisorPagers = await client.db.PagerNumber.findOne({ num: '01' });
    for (const member of members) {
      if (member.roles.includes('701454855952138300') && !supervisorPagers.discordIDs.includes(member.id)) {
        await supervisorPagers.updateOne({ $addToSet: { discordIDs: member.id } });
        const acknowledgement = await resolveStaffInformation(member.id);
        if (acknowledgement?.emailAddress) await supervisorPagers.updateOne({ $addToSet: { emailAddresses: acknowledgement.emailAddress } });
      }
      if (!member.roles.includes('701454855952138300') && supervisorPagers.discordIDs.includes(member.id)) {
        await supervisorPagers.updateOne({ $pull: { discordIDs: member.id } });
        const acknowledgement = await resolveStaffInformation(member.id);
        if (acknowledgement?.emailAddress) await supervisorPagers.updateOne({ $pull: { emailAddresses: acknowledgement.emailAddress } });
      }
    }
    // Board of Directors
    const directorPagers = await client.db.PagerNumber.findOne({ num: '00' });
    for (const member of members) {
      if (member.roles.includes('662163685439045632') && !directorPagers.discordIDs.includes(member.id)) {
        await directorPagers.updateOne({ $addToSet: { discordIDs: member.id } });
        const acknowledgement = await resolveStaffInformation(member.id);
        if (acknowledgement?.emailAddress) await directorPagers.updateOne({ $addToSet: { emailAddresses: acknowledgement.emailAddress } });
      }
      if (!member.roles.includes('662163685439045632') && directorPagers.discordIDs.includes(member.id)) {
        await directorPagers.updateOne({ $pull: { discordIDs: member.id } });
        const acknowledgement = await resolveStaffInformation(member.id);
        if (acknowledgement?.emailAddress) await directorPagers.updateOne({ $pull: { emailAddresses: acknowledgement.emailAddress } });
      }
    }
  }
  client.util.signale.time('pagerint');
  await start(client);
  client.util.signale.timeEnd('pagerint');
  interval = setInterval(async () => {
    client.util.signale.time('pagerint');
    await start(client);
    client.util.signale.timeEnd('pagerint');
  }, 300000);
  return interval;
}
