
package net.voltexstudios.npcConversations.listener;

import com.launchableinc.openai.completion.chat.ChatMessage;
import lombok.RequiredArgsConstructor;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.voltexstudios.npcConversations.NPCConversations;
import net.voltexstudios.npcConversations.session.ConverstionSession;
import net.voltexstudios.npcConversations.util.Messages;
import net.voltexstudios.npcConversations.util.OpenAI;
import net.voltexstudios.npcConversations.util.Type;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;

import java.util.Collection;
import java.util.Collections;
import java.util.List;

@RequiredArgsConstructor
public class ChatHandler implements Listener {

    @EventHandler
    public void onAsyncPlayerChat(AsyncPlayerChatEvent event) {
        Player player = event.getPlayer();

        boolean hasFull = NPCConversations.USER_TYPE.asMap().values().stream().anyMatch(type -> type == Type.FULL);
        if (!NPCConversations.CACHE.asMap().containsKey(player) && !hasFull) {
            return;
        }

        Collection<Player> recipients = switch (NPCConversations.USER_TYPE.asMap().getOrDefault(player, hasFull ? Type.FULL : Type.SINGLE)) {
            case SINGLE -> Collections.singletonList(player);
            case FULL, BROADCAST -> event.getRecipients();
        };

        List<String> list = NPCConversations.getInstance().getConfig().getStringList("format");

        if (!NPCConversations.getInstance().getConfig().getBoolean("use-default-chat", false)) {
            event.setCancelled(true);

            sendMessage(format(list.getFirst(), event.getMessage(), player.getName(), ""), recipients);
        }

        ConverstionSession session = NPCConversations.CACHE.getIfPresent(player);
        if (session == null) return;

        List<ChatMessage> messages = session.getMessages();

        OpenAI.getResponse(NPCConversations.getInstance().getConfig().getConfigurationSection("chatgpt"), messages, event.getMessage()).whenComplete((response, throwable) -> {
            if (throwable != null) {
                throwable.printStackTrace();
                player.sendMessage(
                        NPCConversations.PREFIX.append(
                                NPCConversations.PREFIX.append(
                                        Component.text("An error occurred while processing your message.").color(NamedTextColor.RED)
                                )
                        )
                );
                return;
            }
            sendMessage(format(list.get(1), response, player.getName(), session.getNpc().getName()), recipients);
        });
    }

    private String format(String str, String message, String player, String npcName) {
        return Messages.format(str).replace("%message%", message).replace("%player%", player).replace("%npc%", npcName);
    }

    private void sendMessage(String message, Collection<Player> players) {
        Bukkit.getOnlinePlayers().stream()
                .filter(player -> !players.contains(player) && player.hasPermission("minecraftgpt.receive"))
                .forEach(player -> player.sendMessage(message));

        for (Player player : players)
            player.sendMessage(message);

        if (NPCConversations.getInstance().getConfig().getBoolean("send-messages-to-console", true))
            NPCConversations.getInstance().getServer().getConsoleSender().sendMessage(message);
    }
}
