import {
    ButtonStyle,
    CommandInteraction,
    ComponentType,
    GuildMember,
    Message,
    MessageComponentInteraction
} from "discord.js";
import type Discord from "discord.js";
import { Collection, MongoClient } from "mongodb";
import config from "../config/main.js";
import client from "../utils/client.js";
import * as crypto from "crypto";
import _ from "lodash";
import defaultData from "../config/default.js";

const username = encodeURIComponent(config.mongoOptions.username);
const password = encodeURIComponent(config.mongoOptions.password);

const mongoClient = new MongoClient(
    username
        ? `mongodb://${username}:${password}@${config.mongoOptions.host}?authMechanism=DEFAULT`
        : `mongodb://${config.mongoOptions.host}`,
    { authSource: config.mongoOptions.authSource }
);
await mongoClient.connect();
const database = mongoClient.db();

const collectionOptions = { authdb: config.mongoOptions.authSource, w: "majority" };
const getIV = () => crypto.randomBytes(16);

export class Guilds {
    guilds: Collection<GuildConfig>;
    oldGuilds: Collection<GuildConfig>;
    defaultData: GuildConfig;

    constructor() {
        this.guilds = database.collection<GuildConfig>("guilds");
        this.defaultData = defaultData;
        this.oldGuilds = database.collection<GuildConfig>("oldGuilds");
    }

    async readOld(guild: string): Promise<Partial<GuildConfig>> {
        // console.log("Guild read")
        const entry = await this.oldGuilds.findOne({ id: guild });
        return entry ?? {};
    }

    async read(guild: string): Promise<GuildConfig> {
        // console.log("Guild read")
        const entry = await this.guilds.findOne({ id: guild });
        const data = _.cloneDeep(this.defaultData);
        return _.merge(data, entry ?? {});
    }

    async write(guild: string, set: object | null, unset: string[] | string = []) {
        // console.log("Guild write")
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        const uo: Record<string, any> = {};
        if (!Array.isArray(unset)) unset = [unset];
        for (const key of unset) {
            uo[key] = null;
        }
        const out = { $set: {}, $unset: {} };
        if (set) out.$set = set;
        if (unset.length) out.$unset = uo;
        await this.guilds.updateOne({ id: guild }, out, { upsert: true });
    }

    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    async append(guild: string, key: string, value: any) {
        // console.log("Guild append")
        if (Array.isArray(value)) {
            await this.guilds.updateOne(
                { id: guild },
                {
                    $addToSet: { [key]: { $each: value } }
                },
                { upsert: true }
            );
        } else {
            await this.guilds.updateOne(
                { id: guild },
                {
                    $addToSet: { [key]: value }
                },
                { upsert: true }
            );
        }
    }

    async remove(
        guild: string,
        key: string,
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        value: any,
        innerKey?: string | null
    ) {
        // console.log("Guild remove")
        if (innerKey) {
            await this.guilds.updateOne(
                { id: guild },
                {
                    $pull: { [key]: { [innerKey]: { $eq: value } } }
                },
                { upsert: true }
            );
        } else if (Array.isArray(value)) {
            await this.guilds.updateOne(
                { id: guild },
                {
                    $pullAll: { [key]: value }
                },
                { upsert: true }
            );
        } else {
            await this.guilds.updateOne(
                { id: guild },
                {
                    $pullAll: { [key]: [value] }
                },
                { upsert: true }
            );
        }
    }

    async delete(guild: string) {
        // console.log("Guild delete")
        await this.guilds.deleteOne({ id: guild });
    }
}

interface TranscriptEmbed {
    title?: string;
    description?: string;
    fields?: {
        name: string;
        value: string;
        inline: boolean;
    }[];
    footer?: {
        text: string;
        iconURL?: string;
    };
    color?: number;
    timestamp?: string;
    author?: {
        name: string;
        iconURL?: string;
        url?: string;
    };
}

interface TranscriptComponent {
    type: number;
    style?: ButtonStyle;
    label?: string;
    description?: string;
    placeholder?: string;
    emojiURL?: string;
}

interface TranscriptAuthor {
    username: string;
    discriminator: number;
    nickname?: string;
    id: string;
    iconURL?: string;
    topRole: {
        color: number;
        badgeURL?: string;
    };
    bot: boolean;
}

interface TranscriptAttachment {
    url: string;
    filename: string;
    size: number;
    log?: string;
}

interface TranscriptMessage {
    id: string;
    author: TranscriptAuthor;
    content?: string;
    embeds?: TranscriptEmbed[];
    components?: TranscriptComponent[][];
    editedTimestamp?: number;
    createdTimestamp: number;
    flags?: string[];
    attachments?: TranscriptAttachment[];
    stickerURLs?: string[];
    referencedMessage?: string | [string, string, string]; // the message id, the channel id, the guild id
}

interface TranscriptSchema {
    code: string;
    for: TranscriptAuthor;
    type: "ticket" | "purge";
    guild: string;
    channel: string;
    messages: TranscriptMessage[];
    createdTimestamp: number;
    createdBy: TranscriptAuthor;
}

interface findDocSchema {
    channelID: string;
    messageID: string;
    transcript: string;
}

export class Transcript {
    transcripts: Collection<TranscriptSchema>;
    messageToTranscript: Collection<findDocSchema>;

    constructor() {
        this.transcripts = database.collection<TranscriptSchema>("transcripts");
        this.messageToTranscript = database.collection<findDocSchema>("messageToTranscript");
    }

    async upload(data: findDocSchema) {
        // console.log("Transcript upload")
        await this.messageToTranscript.insertOne(data);
    }

    async create(transcript: Omit<TranscriptSchema, "code">) {
        // console.log("Transcript create")
        let code;
        do {
            code = crypto.randomBytes(64).toString("base64").replace(/=/g, "").replace(/\//g, "_").replace(/\+/g, "-");
        } while (await this.transcripts.findOne({ code: code }));
        const key = crypto
            .randomBytes(32 ** 2)
            .toString("base64")
            .replace(/=/g, "")
            .replace(/\//g, "_")
            .replace(/\+/g, "-")
            .substring(0, 32);
        const iv = getIV().toString("base64").replace(/=/g, "").replace(/\//g, "_").replace(/\+/g, "-");
        for (const message of transcript.messages) {
            if (message.content) {
                const encCipher = crypto.createCipheriv("AES-256-CBC", key, iv);
                message.content = encCipher.update(message.content, "utf8", "base64") + encCipher.final("base64");
            }
        }

        const doc = await this.transcripts.insertOne(Object.assign(transcript, { code: code }), collectionOptions);
        if (doc.acknowledged) {
            client.database.eventScheduler.schedule(
                "deleteTranscript",
                (Date.now() + 1000 * 60 * 60 * 24 * 7).toString(),
                { guild: transcript.guild, code: code, iv: iv, key: key }
            );
            return [code, key, iv];
        } else return [null, null, null];
    }

    async delete(code: string) {
        // console.log("Transcript delete")
        await this.transcripts.deleteOne({ code: code });
    }

    async deleteAll(guild: string) {
        // console.log("Transcript delete")
        const filteredDocs = await this.transcripts.find({ guild: guild }).toArray();
        for (const doc of filteredDocs) {
            await this.transcripts.deleteOne({ code: doc.code });
        }
    }

    async readEncrypted(code: string) {
        // console.log("Transcript read")
        let doc: TranscriptSchema | null = await this.transcripts.findOne({ code: code });
        let findDoc: findDocSchema | null = null;
        if (!doc) findDoc = await this.messageToTranscript.findOne({ transcript: code });
        if (findDoc) {
            const message = await (
                client.channels.cache.get(findDoc.channelID) as Discord.TextBasedChannel | null
            )?.messages.fetch(findDoc.messageID);
            if (!message) return null;
            const attachment = message.attachments.first();
            if (!attachment) return null;
            const transcript = (await fetch(attachment.url)).body;
            if (!transcript) return null;
            const reader = transcript.getReader();
            let data: Uint8Array | null = null;
            let allPacketsReceived = false;
            while (!allPacketsReceived) {
                const { value, done } = await reader.read();
                if (done) {
                    allPacketsReceived = true;
                    continue;
                }
                if (!data) {
                    data = value;
                } else {
                    data = new Uint8Array(Buffer.concat([data, value]));
                }
            }
            if (!data) return null;
            doc = JSON.parse(Buffer.from(data).toString()) as TranscriptSchema;
        }
        if (!doc) return null;
        return doc;
    }

    async read(code: string, key: string, iv: string) {
        // console.log("Transcript read")
        let doc: TranscriptSchema | null = await this.transcripts.findOne({ code: code });
        let findDoc: findDocSchema | null = null;
        if (!doc) findDoc = await this.messageToTranscript.findOne({ transcript: code });
        if (findDoc) {
            const message = await (
                client.channels.cache.get(findDoc.channelID) as Discord.TextBasedChannel | null
            )?.messages.fetch(findDoc.messageID);
            if (!message) return null;
            const attachment = message.attachments.first();
            if (!attachment) return null;
            const transcript = (await fetch(attachment.url)).body;
            if (!transcript) return null;
            const reader = transcript.getReader();
            let data: Uint8Array | null = null;
            // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, no-constant-condition
            while (true) {
                const { value, done } = await reader.read();
                if (done) break;
                if (!data) {
                    data = value;
                } else {
                    data = new Uint8Array(Buffer.concat([data, value]));
                }
            }
            if (!data) return null;
            doc = JSON.parse(Buffer.from(data).toString()) as TranscriptSchema;
        }
        if (!doc) return null;
        for (const message of doc.messages) {
            if (message.content) {
                const decCipher = crypto.createDecipheriv("AES-256-CBC", key, iv);
                message.content = decCipher.update(message.content, "base64", "utf8") + decCipher.final("utf8");
            }
        }
        return doc;
    }

    async createTranscript(
        messages: Message[],
        interaction: MessageComponentInteraction | CommandInteraction,
        member: GuildMember
    ) {
        const interactionMember = await interaction.guild?.members.fetch(interaction.user.id);
        const newOut: Omit<TranscriptSchema, "code"> = {
            type: "ticket",
            for: {
                username: member!.user.username,
                discriminator: parseInt(member!.user.discriminator),
                id: member!.user.id,
                topRole: {
                    color: member!.roles.highest.color
                },
                iconURL: member!.user.displayAvatarURL({ forceStatic: true }),
                bot: member!.user.bot
            },
            guild: interaction.guild!.id,
            channel: interaction.channel!.id,
            messages: [],
            createdTimestamp: Date.now(),
            createdBy: {
                username: interaction.user.username,
                discriminator: parseInt(interaction.user.discriminator),
                id: interaction.user.id,
                topRole: {
                    color: interactionMember?.roles.highest.color ?? 0x000000
                },
                iconURL: interaction.user.displayAvatarURL({ forceStatic: true }),
                bot: interaction.user.bot
            }
        };
        if (member.nickname) newOut.for.nickname = member.nickname;
        if (interactionMember?.roles.icon) newOut.createdBy.topRole.badgeURL = interactionMember.roles.icon.iconURL()!;
        messages.reverse().forEach((message) => {
            const msg: TranscriptMessage = {
                id: message.id,
                author: {
                    username: message.author.username,
                    discriminator: parseInt(message.author.discriminator),
                    id: message.author.id,
                    topRole: {
                        color: message.member!.roles.highest.color
                    },
                    iconURL: message.member!.user.displayAvatarURL({ forceStatic: true }),
                    bot: message.author.bot
                },
                createdTimestamp: message.createdTimestamp
            };
            if (message.member?.nickname) msg.author.nickname = message.member.nickname;
            if (message.member!.roles.icon) msg.author.topRole.badgeURL = message.member!.roles.icon.iconURL()!;
            if (message.content) msg.content = message.content;
            if (message.embeds.length > 0)
                msg.embeds = message.embeds.map((embed) => {
                    const obj: TranscriptEmbed = {};
                    if (embed.title) obj.title = embed.title;
                    if (embed.description) obj.description = embed.description;
                    if (embed.fields.length > 0)
                        obj.fields = embed.fields.map((field) => {
                            return {
                                name: field.name,
                                value: field.value,
                                inline: field.inline ?? false
                            };
                        });
                    if (embed.color) obj.color = embed.color;
                    if (embed.timestamp) obj.timestamp = embed.timestamp;
                    if (embed.footer)
                        obj.footer = {
                            text: embed.footer.text
                        };
                    if (embed.footer?.iconURL) obj.footer!.iconURL = embed.footer.iconURL;
                    if (embed.author)
                        obj.author = {
                            name: embed.author.name
                        };
                    if (embed.author?.iconURL) obj.author!.iconURL = embed.author.iconURL;
                    if (embed.author?.url) obj.author!.url = embed.author.url;
                    return obj;
                });
            if (message.components.length > 0)
                msg.components = message.components.map((component) =>
                    component.components.map((child) => {
                        const obj: TranscriptComponent = {
                            type: child.type
                        };
                        if (child.type === ComponentType.Button) {
                            obj.style = child.style;
                            obj.label = child.label ?? "";
                        } else if (child.type > 2) {
                            obj.placeholder = child.placeholder ?? "";
                        }
                        return obj;
                    })
                );
            if (message.editedTimestamp) msg.editedTimestamp = message.editedTimestamp;
            msg.flags = message.flags.toArray();

            if (message.stickers.size > 0) msg.stickerURLs = message.stickers.map((sticker) => sticker.url);
            if (message.reference)
                msg.referencedMessage = [
                    message.reference.guildId ?? "",
                    message.reference.channelId,
                    message.reference.messageId ?? ""
                ];
            newOut.messages.push(msg);
        });
        return newOut;
    }

    toHumanReadable(transcript: Omit<TranscriptSchema, "code">): string {
        let out = "";
        for (const message of transcript.messages) {
            if (message.referencedMessage) {
                if (Array.isArray(message.referencedMessage)) {
                    out += `> [Crosspost From] ${message.referencedMessage[0]} in ${message.referencedMessage[1]} in ${message.referencedMessage[2]}\n`;
                } else out += `> [Reply To] ${message.referencedMessage}\n`;
            }
            out += `${message.author.nickname ?? message.author.username}#${message.author.discriminator} (${
                message.author.id
            }) (${message.id})`;
            out += ` [${new Date(message.createdTimestamp).toISOString()}]`;
            if (message.editedTimestamp) out += ` [Edited: ${new Date(message.editedTimestamp).toISOString()}]`;
            out += "\n";
            if (message.content) out += `[Content]\n${message.content}\n\n`;
            if (message.embeds) {
                for (const embed of message.embeds) {
                    out += `[Embed]\n`;
                    if (embed.title) out += `| Title: ${embed.title}\n`;
                    if (embed.description) out += `| Description: ${embed.description}\n`;
                    if (embed.fields) {
                        for (const field of embed.fields) {
                            out += `| Field: ${field.name} - ${field.value}\n`;
                        }
                    }
                    if (embed.footer) {
                        out += `|Footer: ${embed.footer.text}\n`;
                    }
                    out += "\n";
                }
            }
            if (message.components) {
                for (const component of message.components) {
                    out += `[Component]\n`;
                    for (const button of component) {
                        out += `| Button: ${button.label ?? button.description}\n`;
                    }
                    out += "\n";
                }
            }
            if (message.attachments) {
                for (const attachment of message.attachments) {
                    out += `[Attachment] ${attachment.filename} (${attachment.size} bytes) ${attachment.url}\n`;
                }
            }
            out += "\n\n";
        }
        return out;
    }
}

export class History {
    histories: Collection<HistorySchema>;

    constructor() {
        this.histories = database.collection<HistorySchema>("history");
    }

    async create(
        type: string,
        guild: string,
        user: Discord.User,
        moderator: Discord.User | null,
        reason: string | null,
        before?: string | null,
        after?: string | null,
        amount?: string | null
    ) {
        // console.log("History create");
        await this.histories.insertOne(
            {
                type: type,
                guild: guild,
                user: user.id,
                moderator: moderator ? moderator.id : null,
                reason: reason,
                occurredAt: new Date(),
                before: before ?? null,
                after: after ?? null,
                amount: amount ?? null
            },
            collectionOptions
        );
    }

    async read(guild: string, user: string, year: number) {
        // console.log("History read");
        const entry = (await this.histories
            .find({
                guild: guild,
                user: user,
                occurredAt: {
                    $gte: new Date(year - 1, 11, 31, 23, 59, 59),
                    $lt: new Date(year + 1, 0, 1, 0, 0, 0)
                }
            })
            .toArray()) as HistorySchema[];
        return entry;
    }

    async delete(guild: string) {
        // console.log("History delete");
        await this.histories.deleteMany({ guild: guild });
    }
}

interface ScanCacheSchema {
    addedAt: Date;
    hash: string;
    data: boolean;
    tags: string[];
}

export class ScanCache {
    scanCache: Collection<ScanCacheSchema>;

    constructor() {
        this.scanCache = database.collection<ScanCacheSchema>("scanCache");
    }

    async read(hash: string) {
        // console.log("ScanCache read");
        return await this.scanCache.findOne({ hash: hash });
    }

    async write(hash: string, data: boolean, tags?: string[]) {
        // console.log("ScanCache write");
        await this.scanCache.insertOne(
            { hash: hash, data: data, tags: tags ?? [], addedAt: new Date() },
            collectionOptions
        );
    }

    async cleanup() {
        // console.log("ScanCache cleanup");
        await this.scanCache.deleteMany({
            addedAt: { $lt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 31) },
            hash: { $not$text: "http" }
        });
    }
}

export class PerformanceTest {
    performanceData: Collection<PerformanceDataSchema>;

    constructor() {
        this.performanceData = database.collection<PerformanceDataSchema>("performance");
    }

    async record(data: PerformanceDataSchema) {
        // console.log("PerformanceTest record");
        data.timestamp = new Date();
        await this.performanceData.insertOne(data, collectionOptions);
    }
    async read() {
        // console.log("PerformanceTest read");
        return await this.performanceData.find({}).toArray();
    }
}

export interface PerformanceDataSchema {
    timestamp?: Date;
    discord: number;
    databaseRead: number;
    resources: {
        cpu: number;
        memory: number;
        temperature: number;
    };
}

export class ModNotes {
    modNotes: Collection<ModNoteSchema>;

    constructor() {
        this.modNotes = database.collection<ModNoteSchema>("modNotes");
    }

    async create(guild: string, user: string, note: string | null) {
        // console.log("ModNotes create");
        await this.modNotes.updateOne({ guild: guild, user: user }, { $set: { note: note } }, { upsert: true });
    }

    async read(guild: string, user: string) {
        // console.log("ModNotes read");
        const entry = await this.modNotes.findOne({ guild: guild, user: user });
        return entry?.note ?? null;
    }

    async delete(guild: string) {
        // console.log("ModNotes delete");
        await this.modNotes.deleteMany({ guild: guild });
    }
}

export class Premium {
    premium: Collection<PremiumSchema>;
    cache: Map<string, [boolean, string, number, boolean, Date]>; // Date indicates the time one hour after it was created
    cacheTimeout = 1000 * 60 * 60; // 1 hour

    constructor() {
        this.premium = database.collection<PremiumSchema>("premium");
        this.cache = new Map<string, [boolean, string, number, boolean, Date]>();
    }

    async updateUser(user: string, level: number) {
        // console.log("Premium updateUser");
        if (!(await this.userExists(user))) await this.createUser(user, level);
        await this.premium.updateOne({ user: user }, { $set: { level: level } }, { upsert: true });
    }

    async userExists(user: string): Promise<boolean> {
        // console.log("Premium userExists");
        const entry = await this.premium.findOne({ user: user });
        return entry ? true : false;
    }
    async createUser(user: string, level: number) {
        // console.log("Premium createUser");
        await this.premium.insertOne({ user: user, appliesTo: [], level: level }, collectionOptions);
    }

    async hasPremium(guild: string): Promise<[boolean, string, number, boolean] | null> {
        // console.log("Premium hasPremium");
        // [Has premium, user giving premium, level, is mod: if given automatically]
        const cached = this.cache.get(guild);
        if (cached && cached[4].getTime() < Date.now()) return [cached[0], cached[1], cached[2], cached[3]];
        const entries = await this.premium.find({}).toArray();
        const members = (await client.guilds.fetch(guild)).members.cache;
        for (const { user } of entries) {
            const member = members.get(user);
            if (member) {
                //TODO: Notify user if they've given premium to a server that has since gotten premium via a mod.
                const modPerms = //TODO: Create list in config for perms
                    member.permissions.has("Administrator") ||
                    member.permissions.has("ManageChannels") ||
                    member.permissions.has("ManageRoles") ||
                    member.permissions.has("ManageEmojisAndStickers") ||
                    member.permissions.has("ManageWebhooks") ||
                    member.permissions.has("ManageGuild") ||
                    member.permissions.has("KickMembers") ||
                    member.permissions.has("BanMembers") ||
                    member.permissions.has("ManageEvents") ||
                    member.permissions.has("ManageMessages") ||
                    member.permissions.has("ManageThreads");
                const entry = entries.find((e) => e.user === member.id);
                if (entry && entry.level === 3 && modPerms) {
                    this.cache.set(guild, [
                        true,
                        member.id,
                        entry.level,
                        true,
                        new Date(Date.now() + this.cacheTimeout)
                    ]);
                    return [true, member.id, entry.level, true];
                }
            }
        }
        const entry = await this.premium.findOne({
            appliesTo: {
                $elemMatch: {
                    $eq: guild
                }
            }
        });
        this.cache.set(guild, [
            entry ? true : false,
            entry?.user ?? "",
            entry?.level ?? 0,
            false,
            new Date(Date.now() + this.cacheTimeout)
        ]);
        return entry ? [true, entry.user, entry.level, false] : null;
    }

    async fetchUser(user: string): Promise<PremiumSchema | null> {
        // console.log("Premium fetchUser");
        const entry = await this.premium.findOne({ user: user });
        if (!entry) return null;
        return entry;
    }

    async checkAllPremium(member?: GuildMember) {
        // console.log("Premium checkAllPremium");
        const entries = await this.premium.find({}).toArray();
        if (member) {
            const entry = entries.find((e) => e.user === member.id);
            if (entry) {
                const expiresAt = entry.expiresAt;
                if (expiresAt) expiresAt < Date.now() ? await this.premium.deleteOne({ user: member.id }) : null;
            }
            const roles = member.roles;
            let level = 0;
            if (roles.cache.has("1066468879309750313")) {
                level = 99;
            } else if (roles.cache.has("1066465491713003520")) {
                level = 1;
            } else if (roles.cache.has("1066439526496604194")) {
                level = 2;
            } else if (roles.cache.has("1066464134322978912")) {
                level = 3;
            }
            await this.updateUser(member.id, level);
            if (level > 0) {
                await this.premium.updateOne({ user: member.id }, { $unset: { expiresAt: "" } });
            } else {
                await this.premium.updateOne(
                    { user: member.id },
                    { $set: { expiresAt: Date.now() + 1000 * 60 * 60 * 24 * 3 } }
                );
            }
        } else {
            const members = await (await client.guilds.fetch("684492926528651336")).members.fetch();
            for (const { roles, id } of members.values()) {
                const entry = entries.find((e) => e.user === id);
                if (entry) {
                    const expiresAt = entry.expiresAt;
                    if (expiresAt) expiresAt < Date.now() ? await this.premium.deleteOne({ user: id }) : null;
                }
                let level: number = 0;
                if (roles.cache.has("1066468879309750313")) {
                    level = 99;
                } else if (roles.cache.has("1066465491713003520")) {
                    level = 1;
                } else if (roles.cache.has("1066439526496604194")) {
                    level = 2;
                } else if (roles.cache.has("1066464134322978912")) {
                    level = 3;
                }
                await this.updateUser(id, level);
                if (level > 0) {
                    await this.premium.updateOne({ user: id }, { $unset: { expiresAt: "" } });
                } else {
                    await this.premium.updateOne(
                        { user: id },
                        { $set: { expiresAt: Date.now() + 1000 * 60 * 60 * 24 * 3 } }
                    );
                }
            }
        }
    }

    async addPremium(user: string, guild: string) {
        // console.log("Premium addPremium");
        const { level } = (await this.fetchUser(user))!;
        this.cache.set(guild, [true, user, level, false, new Date(Date.now() + this.cacheTimeout)]);
        return this.premium.updateOne({ user: user }, { $addToSet: { appliesTo: guild } }, { upsert: true });
    }

    async removePremium(user: string, guild: string) {
        // console.log("Premium removePremium");
        this.cache.set(guild, [false, "", 0, false, new Date(Date.now() + this.cacheTimeout)]);
        return await this.premium.updateOne({ user: user }, { $pull: { appliesTo: guild } });
    }
}

export interface GuildConfig {
    id: string;
    version: number;
    singleEventNotifications: Record<string, boolean>;
    filters: {
        images: {
            NSFW: boolean;
            size: boolean;
        };
        malware: boolean;
        wordFilter: {
            enabled: boolean;
            words: {
                strict: string[];
                loose: string[];
            };
            allowed: {
                users: string[];
                roles: string[];
                channels: string[];
            };
        };
        invite: {
            enabled: boolean;
            allowed: {
                channels: string[];
                roles: string[];
                users: string[];
            };
        };
        pings: {
            mass: number;
            everyone: boolean;
            roles: boolean;
            allowed: {
                roles: string[];
                rolesToMention: string[];
                users: string[];
                channels: string[];
            };
        };
        clean: {
            channels: string[];
            allowed: {
                users: string[];
                roles: string[];
            };
        };
    };
    autoPublish: {
        enabled: boolean;
        channels: string[];
    };
    welcome: {
        enabled: boolean;
        role: string | null;
        ping: string | null;
        channel: string | null;
        message: string | null;
    };
    stats: Record<string, { name: string; enabled: boolean }>;
    logging: {
        logs: {
            enabled: boolean;
            channel: string | null;
            toLog: string;
        };
        staff: {
            channel: string | null;
        };
        attachments: {
            channel: string | null;
            saved: Record<string, string>;
        };
    };
    verify: {
        enabled: boolean;
        role: string | null;
    };
    tickets: {
        enabled: boolean;
        category: string | null;
        types: string;
        customTypes: string[] | null;
        useCustom: boolean;
        supportRole: string | null;
        maxTickets: number;
    };
    moderation: {
        mute: {
            timeout: boolean;
            role: string | null;
            text: string | null;
            link: string | null;
        };
        kick: {
            text: string | null;
            link: string | null;
        };
        ban: {
            text: string | null;
            link: string | null;
        };
        softban: {
            text: string | null;
            link: string | null;
        };
        warn: {
            text: string | null;
            link: string | null;
        };
        role: {
            role: string | null;
            text: null;
            link: null;
        };
        nick: {
            text: string | null;
            link: string | null;
        };
    };
    tracks: {
        name: string;
        retainPrevious: boolean;
        nullable: boolean;
        track: string[];
        manageableBy: string[];
    }[];
    roleMenu: {
        enabled: boolean;
        allowWebUI: boolean;
        options: {
            name: string;
            description: string;
            min: number;
            max: number;
            options: {
                name: string;
                description: string | null;
                role: string;
            }[];
        }[];
    };
    tags: Record<string, string>;
}

export interface HistorySchema {
    type: string;
    guild: string;
    user: string;
    moderator: string | null;
    reason: string | null;
    occurredAt: Date;
    before: string | null;
    after: string | null;
    amount: string | null;
}

export interface ModNoteSchema {
    guild: string;
    user: string;
    note: string | null;
}

export interface PremiumSchema {
    user: string;
    level: number;
    appliesTo: string[];
    expiresAt?: number;
}
