import { Snowflake, TextChannel } from "discord.js";
import { waitForReply } from "knub/dist/helpers";
import { userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
import { commandTypeHelpers as ct } from "../../../commandTypes";
import { LogType } from "../../../data/LogType";
import { logger } from "../../../logger";
import { MutesPlugin } from "../../../plugins/Mutes/MutesPlugin";
import { canActOn, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
import { formatReasonWithAttachments } from "../functions/formatReasonWithAttachments";
import { modActionsCmd } from "../types";
import { LogsPlugin } from "../../Logs/LogsPlugin";

export const MassmuteCmd = modActionsCmd({
  trigger: "massmute",
  permission: "can_massmute",
  description: "Mass-mute a list of user IDs",

  signature: [
    {
      userIds: ct.string({ rest: true }),
    },
  ],

  async run({ pluginData, message: msg, args }) {
    // Limit to 100 users at once (arbitrary?)
    if (args.userIds.length > 100) {
      sendErrorMessage(pluginData, msg.channel, `Can only massmute max 100 users at once`);
      return;
    }

    // Ask for mute reason
    msg.channel.send("Mute reason? `cancel` to cancel");
    const muteReasonReceived = await waitForReply(pluginData.client, msg.channel as TextChannel, msg.author.id);
    if (
      !muteReasonReceived ||
      !muteReasonReceived.content ||
      muteReasonReceived.content.toLowerCase().trim() === "cancel"
    ) {
      sendErrorMessage(pluginData, msg.channel, "Cancelled");
      return;
    }

    const muteReason = formatReasonWithAttachments(muteReasonReceived.content, [...msg.attachments.values()]);

    // Verify we can act upon all users
    for (const userId of args.userIds) {
      const member = pluginData.guild.members.cache.get(userId as Snowflake);
      if (member && !canActOn(pluginData, msg.member, member)) {
        sendErrorMessage(pluginData, msg.channel, "Cannot massmute one or more users: insufficient permissions");
        return;
      }
    }

    // Ignore automatic mute cases and logs for these users
    // We'll create our own cases below and post a single "mass muted" log instead
    args.userIds.forEach((userId) => {
      // Use longer timeouts since this can take a while
      pluginData.state.serverLogs.ignoreLog(LogType.MEMBER_MUTE, userId, 120 * 1000);
    });

    // Show loading indicator
    const loadingMsg = await msg.channel.send("Muting...");

    // Mute everyone and count fails
    const modId = msg.author.id;
    const failedMutes: string[] = [];
    const mutesPlugin = pluginData.getPlugin(MutesPlugin);
    for (const userId of args.userIds) {
      try {
        await mutesPlugin.muteUser(userId, 0, `Mass mute: ${muteReason}`, {
          caseArgs: {
            modId,
          },
        });
      } catch (e) {
        logger.info(e);
        failedMutes.push(userId);
      }
    }

    // Clear loading indicator
    loadingMsg.delete();

    const successfulMuteCount = args.userIds.length - failedMutes.length;
    if (successfulMuteCount === 0) {
      // All mutes failed
      sendErrorMessage(pluginData, msg.channel, "All mutes failed. Make sure the IDs are valid.");
    } else {
      // Success on all or some mutes
      pluginData.getPlugin(LogsPlugin).logMassMute({
        mod: msg.author,
        count: successfulMuteCount,
      });

      if (failedMutes.length) {
        sendSuccessMessage(
          pluginData,
          msg.channel,
          `Muted ${successfulMuteCount} users, ${failedMutes.length} failed: ${failedMutes.join(" ")}`,
        );
      } else {
        sendSuccessMessage(pluginData, msg.channel, `Muted ${successfulMuteCount} users successfully`);
      }
    }
  },
});
