import * as Discord from "discord.js";
import { toHexArray } from "./calculate.js";
import { promisify } from "util";
import generateKeyValueList from "./generateKeyValueList.js";
import client from "./client.js";
import { DiscordAPIError } from "discord.js";
import { Stream } from "node:stream";
import EmojiEmbed from "./generateEmojiEmbed.js";

const wait = promisify(setTimeout);

export interface LoggerOptions {
    meta: {
        type: string;
        displayName: string;
        calculateType: string;
        color: number;
        emoji: string;
        timestamp: number;
        files?: (
            | Discord.BufferResolvable
            | Stream
            | Discord.JSONEncodable<Discord.APIAttachment>
            | Discord.Attachment
            | Discord.AttachmentBuilder
            | Discord.AttachmentPayload
        )[];
        showDetails?: boolean;
    };
    list: Record<string | symbol | number, unknown>;
    hidden: {
        guild: string;
    };
    separate?: {
        start?: string;
        end?: string;
    };
}

async function isLogging(guild: string, type: string): Promise<boolean> {
    const config = await client.database.guilds.read(guild);
    if (!config.logging.logs.enabled) return false;
    if (!config.logging.logs.channel) return false;
    if (!toHexArray(config.logging.logs.toLog).includes(type)) {
        return false;
    }
    return true;
}

export const Logger = {
    renderUser(user: Discord.User | string) {
        if (typeof user === "string") user = client.users.cache.get(user)!;
        return `${user.username} [<@${user.id}>]`;
    },
    renderTime(t: number) {
        if (isNaN(t)) return "Unknown";
        t = Math.floor((t /= 1000));
        return `<t:${t}:D> at <t:${t}:T>`;
    },
    renderDelta(t: number) {
        if (isNaN(t)) return "Unknown";
        t = Math.floor((t /= 1000));
        return `<t:${t}:R> (<t:${t}:D> at <t:${t}:T>)`;
    },
    renderNumberDelta(num1: number, num2: number) {
        const delta = num2 - num1;
        return `${num1} -> ${num2} (${delta > 0 ? "+" : ""}${delta})`;
    },
    entry(
        value: string | number | boolean | null | (string | boolean)[],
        displayValue: string
    ): { value: string | boolean | null | (string | boolean | number)[]; displayValue: string } {
        if (typeof value === "number") value = value.toString();
        return { value: value, displayValue: displayValue };
    },
    renderChannel(channel: Discord.GuildChannel | Discord.ThreadChannel | string) {
        if (typeof channel === "string")
            channel = client.channels.cache.get(channel) as Discord.GuildChannel | Discord.ThreadChannel;
        return `${channel.name} [<#${channel.id}>]`;
    },
    renderRole(role: Discord.Role | string, guild?: Discord.Guild | string) {
        if (typeof role === "string")
            role = (typeof guild === "string" ? client.guilds.cache.get(guild) : guild)!.roles.cache.get(role)!;
        return `${role.name} [<@&${role.id}>]`;
    },
    renderEmoji(emoji: Discord.GuildEmoji) {
        return `<${emoji.animated ? "a" : ""}:${emoji.name}:${emoji.id}> [\`:${emoji.name}:\`]`;
    },
    NucleusColors: {
        red: 0xf27878,
        yellow: 0xf2d478,
        green: 0x68d49e
    },
    async getAuditLog(
        guild: Discord.Guild,
        event: Discord.GuildAuditLogsResolvable,
        delay?: number
    ): Promise<Discord.GuildAuditLogsEntry[]> {
        if (!guild.members.me?.permissions.has("ViewAuditLog")) return [];
        await wait(delay ?? 250);
        try {
            const auditLog = (await guild.fetchAuditLogs({ type: event })).entries.map((m) => m);
            return auditLog as Discord.GuildAuditLogsEntry[];
        } catch (e) {
            if (e instanceof DiscordAPIError) return [];
            throw e;
        }
    },
    async log(log: LoggerOptions): Promise<void> {
        if (!(await isLogging(log.hidden.guild, log.meta.calculateType))) return;
        const config = await client.database.guilds.read(log.hidden.guild);

        if (config.logging.logs.channel) {
            const channel = (await client.channels.fetch(config.logging.logs.channel)) as Discord.TextChannel | null;
            const description: Record<string, string> = {};
            Object.entries(log.list).map((entry) => {
                const key: string = entry[0];
                // eslint-disable-next-line @typescript-eslint/no-explicit-any
                const value: any = entry[1];
                if (value.displayValue) {
                    description[key] = value.displayValue;
                } else {
                    description[key] = value;
                }
            });
            if (channel) {
                log.separate = log.separate ?? {};
                const messageOptions: Parameters<Discord.TextChannel["send"]>[0] = {};
                const components: Discord.ActionRowBuilder<Discord.ButtonBuilder> = new Discord.ActionRowBuilder();
                messageOptions.embeds = [
                    new EmojiEmbed()
                        .setEmoji(log.meta.emoji)
                        .setTitle(log.meta.displayName)
                        .setDescription(
                            (log.separate.start ? log.separate.start + "\n" : "") +
                                generateKeyValueList(description) +
                                (log.separate.end ? "\n" + log.separate.end : "")
                        )
                        .setTimestamp(log.meta.timestamp)
                        .setColor(log.meta.color)
                ];
                if (log.meta.files) messageOptions.files = log.meta.files;
                if (log.meta.showDetails) {
                    components.addComponents(
                        new Discord.ButtonBuilder()
                            .setCustomId("log:showDetails")
                            .setLabel("Show Details")
                            .setStyle(Discord.ButtonStyle.Primary)
                    );
                    messageOptions.components = [components];
                }
                await channel.send(messageOptions);
            }
        }
    },
    isLogging
};

export default {};
