package io.github.thetrouper.sentinel.server;

import io.github.itzispyder.pdk.utils.discord.DiscordEmbed;
import io.github.itzispyder.pdk.utils.discord.DiscordWebhook;
import io.github.thetrouper.sentinel.Sentinel;
import io.github.thetrouper.sentinel.data.Emojis;
import io.github.thetrouper.sentinel.data.FAT;
import io.github.thetrouper.sentinel.data.FilterSeverity;
import io.github.thetrouper.sentinel.server.functions.ReportFalsePositives;
import io.github.thetrouper.sentinel.server.util.ServerUtils;
import io.github.thetrouper.sentinel.server.util.Text;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
import org.bukkit.entity.Player;
import org.bukkit.event.player.AsyncPlayerChatEvent;

import java.math.RoundingMode;
import java.text.DecimalFormat;

import static io.github.thetrouper.sentinel.server.functions.AntiSpam.heatMap;
import static io.github.thetrouper.sentinel.server.functions.AntiSpam.lastMessageMap;
import static io.github.thetrouper.sentinel.server.functions.ProfanityFilter.*;

public class FilterAction {

    public static void filterPunish(AsyncPlayerChatEvent e, FAT type, Double similarity, FilterSeverity severity) {
        String report = ReportFalsePositives.generateReport(e);
        TextComponent staffNotif = Component.text("");
        TextComponent playerWarning = Component.text("");
        Player offender = e.getPlayer();
        switch (type) {
            case BLOCK_SPAM -> {
                staffNotif = Component
                        .text(Text.prefix(String.format(Sentinel.language.get("spam-notification"),
                            offender.getName(),
                            heatMap.get(offender),
                            Sentinel.mainConfig.chat.antiSpam.punishHeat
                        )))
                        .hoverEvent(Component.text(String.format(Sentinel.language.get("spam-notification-hover"),
                            lastMessageMap.get(offender),
                            e.getMessage(),
                            similarity
                        )));

                playerWarning = Component.text(Text.prefix(Sentinel.language.get("spam-block-warn")));
            }
            case SPAM_PUNISH -> {
                staffNotif = Component.text(Text.prefix(String.format(Sentinel.language.get("spam-mute-notification"),
                            offender.getName(),
                            heatMap.get(offender),
                            Sentinel.mainConfig.chat.antiSpam.punishHeat
                        )))
                        .hoverEvent(Component.text(String.format(Sentinel.language.get("spam-notification-hover"),
                                lastMessageMap.get(offender),
                                e.getMessage(),
                                similarity
                        )));

                playerWarning = Component.text(Sentinel.language.get("spam-mute-warn"));
                sendConsoleLog(offender,e,type);
                sendDiscordLog(offender,e,type);
            }
            case BLOCK_SWEAR -> {
                staffNotif = Component.text(Text.prefix(String.format(Sentinel.language.get("profanity-block-notification"),
                                offender.getName(),
                                scoreMap.get(offender),
                                Sentinel.mainConfig.chat.antiSwear.punishScore
                            )))
                        .hoverEvent(Component.text(String.format(Sentinel.language.get("severity-notification-hover"),
                                e.getMessage(),
                                highlightProfanity(fullSimplify(e.getMessage())),
                                severity.name()
                            )));

                playerWarning = Component.text(Text.prefix(Sentinel.language.get("profanity-block-warn")))
                        .hoverEvent(Component.text(Sentinel.language.get("action-automatic-reportable")))
                        .clickEvent(ClickEvent.runCommand("sentinelcallback fpreport " + report));
            }
            case SWEAR_PUNISH -> {
                staffNotif = Component.text(Text.prefix(String.format(Sentinel.language.get("profanity-mute-notification"),
                                offender.getName(),
                                scoreMap.get(offender),
                                Sentinel.mainConfig.chat.antiSwear.punishScore
                            )))
                        .hoverEvent(Component.text(String.format(Sentinel.language.get("severity-notification-hover"),
                                e.getMessage(),
                                highlightProfanity(fullSimplify(e.getMessage())),
                                severity.name()
                            )));

                playerWarning = Component.text(Text.prefix(Sentinel.language.get("profanity-mute-warn")))
                        .hoverEvent(Component.text(Sentinel.language.get("action-automatic-reportable")));
                sendConsoleLog(offender,e,type);
                sendDiscordLog(offender,e,type);
            }
            case SLUR_PUNISH -> {
                staffNotif = Component.text(Text.prefix(String.format(Sentinel.language.get("slur-mute-notification"),
                                offender.getName(),
                                scoreMap.get(offender),
                                Sentinel.mainConfig.chat.antiSwear.punishScore
                            )))
                        .hoverEvent(Component.text(String.format(Sentinel.language.get("severity-notification-hover"),
                                e.getMessage(),
                                highlightProfanity(fullSimplify(e.getMessage())),
                                severity.name()
                            )));

                playerWarning = Component.text(Text.prefix(Sentinel.language.get("slur-mute-warn")))
                        .hoverEvent(Component.text(Sentinel.language.get("action-automatic-reportable")));
                sendConsoleLog(offender,e,type);
                sendDiscordLog(offender,e,type);
            }
        }
        if (type.getExecutedCommand() != null) {
            ServerUtils.sendCommand(type.getExecutedCommand().replace("%player%", offender.getName()));
        }
        staffNotif = staffNotif.clickEvent(ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/sentinelcallback fpreport " + report));

        for (Player staff : ServerUtils.getStaff()) {
            staff.sendMessage(staffNotif);
        }
        e.getPlayer().sendMessage(playerWarning);
    }

    /*public static void filterAction(Player offender, AsyncPlayerChatEvent e, String highlighted, FilterSeverity severity, Double similarity, FAT type) {
        String report = ReportFalsePositives.generateReport(e);
        DecimalFormat fs = new DecimalFormat("##.#");
        fs.setRoundingMode(RoundingMode.DOWN);

        TextComponent warn = createTextComponent(Text.prefix(Sentinel.language.get(type.getWarnTranslationKey())));
        warn.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(Sentinel.language.get("action-automatic-reportable"))));
        warn.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/sentinelcallback fpreport " + report));

        TextComponent notif = createTextComponent(Text.prefix((type != FAT.SPAM_PUNISH && type != FAT.BLOCK_SPAM ?
                Sentinel.language.get("severity-notification-hover").formatted(e.getMessage(), highlighted, severity.name().toLowerCase().replace("_"," ")) :
                Sentinel.language.get("spam-notification-hover").formatted(e.getMessage(), lastMessageMap.get(offender), fs.format(similarity)))));
        notif.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(Sentinel.language.get("severity-notification-hover"))));
        notif.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/sentinelcallback fpreport " + report));

        sendMessages(offender, warn, notif, type);

        if (shouldLogSwears(type)) {
            sendDiscordLog(offender, e, type);
            sendConsoleLog(offender, e, type);
        }
    }

    private static void sendMessages(Player offender, TextComponent warn, TextComponent notif, FAT type) {
        offender.spigot().sendMessage(warn);

        String notifText = Sentinel.language.get(type.getNotifTranslationKey());
        notif.setText(Text.prefix((type != FAT.SPAM_PUNISH && type != FAT.BLOCK_SPAM ?
                notifText.formatted(offender.getName(), scoreMap.get(offender), Sentinel.mainConfig.chat.antiSwear.punishScore) :
                notifText.formatted(offender.getName(), heatMap.get(offender), Sentinel.mainConfig.chat.antiSpam.punishHeat))));

        ServerUtils.forEachStaff(staffmember -> staffmember.spigot().sendMessage(notif));

        if (type.getExecutedCommand() != null) {
            ServerUtils.sendCommand(type.getExecutedCommand().replace("%player%", offender.getName()));
        }
    }

    private static TextComponent createTextComponent(String text) {
        TextComponent component = new TextComponent();
        component.setText(text);
        return component;
    }*/

    private static boolean shouldLogSwears(FAT type) {
        return (type == FAT.SWEAR_PUNISH || type == FAT.SLUR_PUNISH) && Sentinel.mainConfig.chat.antiSwear.logSwears
                || (type == FAT.SPAM_PUNISH && Sentinel.mainConfig.chat.antiSpam.logSpam);
    }

    public static void sendConsoleLog(Player offender, AsyncPlayerChatEvent e, FAT type) {
        StringBuilder log = new StringBuilder().append(String.format("]=- %s -=[",type.getTitle()));
        log.append(String.format("\nPlayer: %s",offender.getName()));
        log.append(String.format("\n> UUID: %s",offender.getUniqueId()));
        switch (type) {
            case SPAM_PUNISH -> {
                log.append(String.format("\n> Heat: %1$s/%2$s",heatMap.get(offender),Sentinel.mainConfig.chat.antiSpam.punishHeat));
                log.append(String.format("\nMessage: %s", e.getMessage()));
                log.append(String.format("\nReduced: %s",fullSimplify(e.getMessage())));
            }
            case SWEAR_PUNISH, SLUR_PUNISH -> {
                log.append(String.format("\n> Score: %1$s/%2$s",heatMap.get(offender),Sentinel.mainConfig.chat.antiSwear.punishScore));
                log.append(String.format("\nPrevious: %s",lastMessageMap.get(offender)));
                log.append(String.format("\nCurrent: %s",e.getMessage()));
            }
            default -> {
                log.append("\nYou shouldn't be seeing this! Please report this message, and the context surrounding it!");
                log.append(String.format("\n> Heat: %1$s/%2$s",heatMap.get(offender),Sentinel.mainConfig.chat.antiSpam.punishHeat));
                log.append(String.format("\nMessage: %s",e.getMessage()));
                log.append(String.format("\nReduced: %s",fullSimplify(e.getMessage())));
                log.append(String.format("\n> Score: %1$s/%2$s",heatMap.get(offender),Sentinel.mainConfig.chat.antiSwear.punishScore));
                log.append(String.format("\nPrevious: %s",lastMessageMap.get(offender)));
                log.append(String.format("\nCurrent: %s",e.getMessage()));
            }
        }
        log.append(String.format("\nExecuted: %s",type.getExecutedCommand()));
        Sentinel.log.info(String.valueOf(log));
    }

    private static void sendDiscordLog(Player offender, AsyncPlayerChatEvent e, FAT type) {
        String supertitle = type.getTitle();
        String title = offender.getName() + " has triggered the " + type.getName() + "!";

        String executed = type.getExecutedCommand() != null ? type.getExecutedCommand() : "Nothing, its a standard flag. You shouldn't be seeing this, please report it.";
        StringBuilder description = new StringBuilder();

        String historyTitle = "You found a bug! :D";
        String historyValue = "Congratulations.";

        String currentTitle = "Now go report it!";
        String currentValue = ">:(";

        description.append(String.format("%1$sPlayer: `%2$s` %3$s",Emojis.rightSort,offender.getName(),Emojis.target));
        switch (type) {
            case SPAM_PUNISH -> {
                description.append(String.format("\n%1$s%2$sHeat: `%3$s/%4$s`",
                        Emojis.space,
                        Emojis.arrowRight,
                        heatMap.get(offender),
                        Sentinel.mainConfig.chat.antiSpam.punishHeat
                ));
                historyTitle = "Previous: ";
                historyValue = lastMessageMap.get(offender);

                currentTitle = "Current: ";
                currentValue = e.getMessage();
            }
            case SWEAR_PUNISH, SLUR_PUNISH -> {
                description.append(String.format("\n%1$s%2$sScore: `%3$s/%4$s`",
                        Emojis.space,
                        Emojis.arrowRight,
                        scoreMap.get(offender),
                        Sentinel.mainConfig.chat.antiSwear.punishScore
                ));
                historyTitle = "Message: ";
                historyValue = e.getMessage();

                currentTitle = "Reduced: ";
                currentValue = highlightProfanity(e.getMessage(),"||", "||");
            }
        }

        try {
            ServerUtils.sendDebugMessage("Executing webhook...");
            DiscordWebhook.create()
                    .username("Sentinel Anti-Nuke | Logs")
                    .avatar("https://r2.e-z.host/d440b58a-ba90-4839-8df6-8bba298cf817/3lwit5nt.png")
                    .addEmbed(DiscordEmbed.create()
                            .author(new DiscordEmbed.Author(supertitle,"https://builtbybit.com/resources/sentinel-anti-nuke.30130/",null))
                            .title(title)
                            .desc(String.valueOf(description))
                            .addField(new DiscordEmbed.Field(historyTitle,historyValue,true))
                            .addField(new DiscordEmbed.Field(currentTitle,currentValue,true))
                            .addField(new DiscordEmbed.Field("Executed: ", executed.replaceAll("%player%",offender.getName()),false))
                            .thumbnail("https://crafatar.com/avatars/" + offender.getUniqueId() + "?size=64&&overlay")
                            .color(type.getColor())
                            .build()).send(Sentinel.mainConfig.plugin.webhook);

        } catch (Exception ex) {
            ServerUtils.sendDebugMessage("Filter Actions: Epic webhook failure!!!");
            Sentinel.log.info(ex.toString());
        }



    }
    /*
    public static void filterAction(Player offender, AsyncPlayerChatEvent e, String highlighted, String severity, Double similarity, FAT type) {
        String report = ReportFalsePositives.generateReport(e);

        TextComponent warn = new TextComponent();
        warn.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(Sentinel.language.get("action-automatic-reportable"))));
        warn.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/sentinelcallback fpreport " + report));

        DecimalFormat fs = new DecimalFormat("##.#");
        fs.setRoundingMode(RoundingMode.DOWN);

        TextComponent notif = new TextComponent();
        notif.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText((type != FAT.SPAM_PUNISH && type != FAT.BLOCK_SPAM ? Sentinel.language.get("severity-notification-hover").formatted(e.getMessage(), highlighted, severity) : Sentinel.language.get("spam-notification-hover").formatted(e.getMessage(),lastMessageMap.get(offender),fs.format(similarity))))));
        notif.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/sentinelcallback fpreport " + report));

        warn.setText(Text.prefix(Sentinel.language.get(type.getWarnTranslationKey())));
        offender.spigot().sendMessage(warn);

        String notiftext = Sentinel.language.get(type.getNotifTranslationKey());

        notif.setText(Text.prefix((type != FAT.SPAM_PUNISH && type != FAT.BLOCK_SPAM ? notiftext.formatted(offender.getName(), scoreMap.get(offender), Sentinel.mainConfig.chat.antiSwear.punishScore) : notiftext.formatted(offender.getName(),heatMap.get(offender),Sentinel.mainConfig.chat.antiSpam.punishHeat))));

        ServerUtils.forEachStaff(staffmember -> {
            staffmember.spigot().sendMessage(notif);
        });

        if (type.getExecutedCommand() != null) {
            ServerUtils.sendCommand(type.getExecutedCommand().replace("%player%", offender.getName()));
        }

        if (type == FAT.SWEAR_PUNISH && Sentinel.mainConfig.chat.antiSwear.logSwears) {
            sendDiscordLog(offender,e,type);
            sendConsoleLog(offender,e,type);
        }

        if (type == FAT.SLUR_PUNISH && Sentinel.mainConfig.chat.antiSwear.logSwears) {
            sendDiscordLog(offender,e,type);
            sendConsoleLog(offender,e,type);
        }
        if (type == FAT.SPAM_PUNISH && Sentinel.mainConfig.chat.antiSpam.logSpam) {
            sendDiscordLog(offender,e,type);
            sendConsoleLog(offender,e,type);
        }
    }*/



}
