import React, { SetStateAction, useState } from "react";
import "./LogChannels.css";

const LOG_TYPES = {
  "MEMBER_WARN": "Member warned",
  "MEMBER_MUTE": "Member muted",
  "MEMBER_UNMUTE": "Member unmuted",
  "MEMBER_MUTE_EXPIRED": "Mute expired",
  "MEMBER_KICK": "Member kicked",
  "MEMBER_BAN": "Member banned",
  "MEMBER_UNBAN": "Member unbanned",
  "MEMBER_FORCEBAN": "Member forcebanned",
  "MEMBER_SOFTBAN": "Member softbanned",
  "MEMBER_JOIN": "Member joined",
  "MEMBER_LEAVE": "Member left",
  "MEMBER_ROLE_ADD": "Member, role added",
  "MEMBER_ROLE_REMOVE": "Member, role removed",
  "MEMBER_NICK_CHANGE": "Member nickname changed",
  "MEMBER_USERNAME_CHANGE": "Member username changed",
  "MEMBER_RESTORE": "Member roles restored",
  "CHANNEL_CREATE": "Channel created",
  "CHANNEL_DELETE": "Channel deleted",
  "CHANNEL_UPDATE": "Channel updated",
  "THREAD_CREATE": "Thread created",
  "THREAD_DELETE": "Thread deleted",
  "THREAD_UPDATE": "Thread updated",
  "ROLE_CREATE": "Role created",
  "ROLE_DELETE": "Role deleted",
  "ROLE_UPDATE": "Role updated",
  "MESSAGE_EDIT": "Message edited",
  "MESSAGE_DELETE": "Message deleted",
  "MESSAGE_DELETE_BULK": "Messages deleted in bulk",
  "MESSAGE_DELETE_BARE": "Message deleted (bare)",
  "VOICE_CHANNEL_JOIN": "Voice channel join",
  "VOICE_CHANNEL_LEAVE": "Voice channel leave",
  "VOICE_CHANNEL_MOVE": "Voice channel move",
  "STAGE_INSTANCE_CREATE": "Stage created",
  "STAGE_INSTANCE_DELETE": "Stage deleted",
  "STAGE_INSTANCE_UPDATE": "Stage updated",
  "EMOJI_CREATE": "Emoji created",
  "EMOJI_DELETE": "Emoji deleted",
  "EMOJI_UPDATE": "Emoji updated",
  "STICKER_CREATE": "Sticker created",
  "STICKER_DELETE": "Sticker deleted",
  "STICKER_UPDATE": "Sticker updated",
  "COMMAND": "Command used",
  "MESSAGE_SPAM_DETECTED": "Message spam detected",
  "CENSOR": "Message censored",
  "CLEAN": "Messages cleaned",
  "CASE_CREATE": "Case created",
  "MASSBAN": "Massbanned",
  "MASSMUTE": "Massmuted",
  "MEMBER_TIMED_MUTE": "Member temporarily muted",
  "MEMBER_TIMED_UNMUTE": "Member, scheduled unmute",
  "MEMBER_JOIN_WITH_PRIOR_RECORDS": "Member joined with prior records",
  "OTHER_SPAM_DETECTED": "Non-message spam detected",
  "MEMBER_ROLE_CHANGES": "Member roles changed",
  "VOICE_CHANNEL_FORCE_MOVE": "Force-moved to a voice channel",
  "CASE_UPDATE": "Case updated",
  "MEMBER_MUTE_REJOIN": "Muted member rejoined",
  "SCHEDULED_MESSAGE": "Scheduled message to be posted",
  "POSTED_SCHEDULED_MESSAGE": "Posted scheduled message",
  "BOT_ALERT": "Bot alert",
  "AUTOMOD_ACTION": "Automod action",
  "SCHEDULED_REPEATED_MESSAGE": "Scheduled message to be posted repeatedly",
  "REPEATED_MESSAGE": "Set a message to be posted repeatedly",
  "MESSAGE_DELETE_AUTO": "Message deleted (auto)",
  "SET_ANTIRAID_USER": "Set antiraid (user)",
  "SET_ANTIRAID_AUTO": "Set antiraid (auto)",
  "MASS_ASSIGN_ROLES": "Mass-assigned roles",
  "MASS_UNASSIGN_ROLES": "Mass-unassigned roles",
  "MEMBER_NOTE": "Member noted",
  "CASE_DELETE": "Case deleted",
  "DM_FAILED": "Failed to DM member",
};

const sortedLogTypes = Object.fromEntries(
  Object.entries(LOG_TYPES)
    .sort((a, b) => {
      if (a[1].toLowerCase() > b[1].toLowerCase()) return 1;
      if (a[1].toLowerCase() < b[1].toLowerCase()) return -1;
      if (a[0].toLowerCase() > b[0].toLowerCase()) return 1;
      if (a[0].toLowerCase() < b[0].toLowerCase()) return -1;
      return 0;
    })
) as typeof LOG_TYPES;

type LOG_TYPE = keyof typeof LOG_TYPES;

export interface LogChannel {
  id: string;
  includeExclude: "include" | "exclude";
  logTypes: Set<LOG_TYPE>;
}

interface Props {
  logChannels: LogChannel[];
  setLogChannels: React.Dispatch<SetStateAction<LogChannel[]>>;
}

export function LogChannels({ logChannels, setLogChannels }: Props) {
  function addLogChannel(props: Partial<LogChannel> = {}) {
    setLogChannels(_logChannels => {
      return [..._logChannels, {
        id: "",
        includeExclude: "include",
        logTypes: new Set(),
        ...props,
      }];
    });
  }

  function deleteLogChannel(index) {
    setLogChannels(_logChannels => {
      const newArr = [..._logChannels];
      newArr.splice(index, 1);
      return newArr;
    });
  }

  function addReverseLogChannel() {
    const includedLogTypesInOtherLogChannels = new Set(logChannels.map(l => Array.from(l.logTypes)).flat());
    addLogChannel({
      includeExclude: "exclude",
      logTypes: includedLogTypesInOtherLogChannels,
    });
  }

  function setId(index: number, id: string) {
    setLogChannels(_logChannels => {
      _logChannels[index].id = id;
      return [..._logChannels];
    });
  }

  function setIncludeExclude(index: number, includeExclude: LogChannel["includeExclude"]) {
    setLogChannels(_logChannels => {
      _logChannels[index].includeExclude = includeExclude;
      return [..._logChannels];
    });
  }

  function toggleLogType(index: number, logType: LOG_TYPE, enabled: boolean) {
    setLogChannels(_logChannels => {
      if (enabled) {
        _logChannels[index].logTypes.add(logType);
      } else {
        _logChannels[index].logTypes.delete(logType);
      }

      return [..._logChannels];
    });
  }

  return (
    <div className="LogChannels">
      {logChannels.map((logChannel, index) => (
        <div className="log-channel">
          <label>
            ID: <input value={logChannel.id} onChange={e => setId(index, e.target.value)} />
          </label>
          <label>
            Mode:
            <select value={logChannel.includeExclude} onChange={e => setIncludeExclude(index, e.target.value as LogChannel["includeExclude"])}>
              <option value={"include"}>Include</option>
              <option value={"exclude"}>Exclude</option>
            </select>
          </label>
          <div className="log-types">
            {Object.entries(sortedLogTypes).map(([logType, description]) => (
              <label>
                <input
                  type="checkbox"
                  checked={logChannel.logTypes.has(logType as LOG_TYPE)}
                  onChange={e => toggleLogType(index, logType as LOG_TYPE, e.target.checked)}
                />
                {description}
              </label>
            ))}
          </div>
          <button onClick={() => deleteLogChannel(index)}>Delete</button>
        </div>
      ))}
      <button onClick={() => addLogChannel()}>Add</button>
      <button onClick={() => addReverseLogChannel()}>Add "everything else"</button>
    </div>
  );
}
