/*
    This file is a part of the SteamWar software.

    Copyright (C) 2020  SteamWar.de-Serverteam

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package de.steamwar.velocitycore.discord.listeners;

import de.steamwar.messages.Chatter;
import de.steamwar.messages.ChatterGroup;
import de.steamwar.messages.Message;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.UserPerm;
import de.steamwar.velocitycore.discord.DiscordBot;
import de.steamwar.velocitycore.discord.DiscordTicketType;
import de.steamwar.velocitycore.discord.channels.DiscordChannel;
import de.steamwar.velocitycore.discord.channels.InteractionReply;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.entities.emoji.Emoji;
import net.dv8tion.jda.api.events.interaction.component.GenericComponentInteractionCreateEvent;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.buttons.Button;
import net.dv8tion.jda.api.utils.SplitUtil;
import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder;
import net.dv8tion.jda.api.utils.messages.MessageCreateData;
import net.kyori.adventure.text.event.ClickEvent;
import org.jetbrains.annotations.NotNull;

import java.awt.*;
import java.time.Instant;
import java.util.LinkedList;
import java.util.stream.Collectors;

public class DiscordTicketHandler extends ListenerAdapter {

    private static final String TICKET_CATEGORY = DiscordBot.getInstance().getConfig().getTicketcategory();
    private static final String TICKET_LOG = DiscordBot.getInstance().getConfig().channel("ticketlog");
    private static final String TICKET_CHANNEL = DiscordBot.getInstance().getConfig().channel("ticket");

    public static void openTicket(GenericComponentInteractionCreateEvent event) {
        DiscordTicketType ticketType = DiscordTicketType.valueOf(event.getComponentId().toUpperCase());
        SteamwarUser user = SteamwarUser.get(event.getUser().getIdLong());

        TextChannel ticketChannel = event.getGuild().getCategoryById(TICKET_CATEGORY).createTextChannel((user == null ? event.getUser().getName() : user.getUserName()) + "-" + event.getComponentId() + "-" + System.currentTimeMillis() % 1000).complete();
        ticketChannel.getPermissionContainer().upsertPermissionOverride(event.getMember()).setAllowed(
                Permission.VIEW_CHANNEL,
                Permission.MESSAGE_SEND,
                Permission.MESSAGE_ATTACH_FILES,
                Permission.MESSAGE_ADD_REACTION,
                Permission.MESSAGE_EMBED_LINKS,
                Permission.MESSAGE_HISTORY).complete();
        ticketChannel.getManager().setTopic(event.getUser().getId()).complete();

        DiscordChannel channel = new DiscordChannel(DiscordChannel.userOrPublic(event.getUser()), ticketChannel);
        channel.send(new MessageCreateBuilder()
                .setEmbeds(new EmbedBuilder()
                        .setTitle(channel.parseToPlain("DC_TICKET_TITLE"))
                        .setDescription(channel.parseToPlain(ticketType.introduction()))
                        .setColor(Color.GREEN)
                        .build())
                .setComponents(ActionRow.of(Button.danger("close-" + ticketChannel.getName(), channel.parseToPlain("DC_TICKET_CLOSE")).withEmoji(Emoji.fromUnicode("U+26A0")))));

        InteractionReply.reply(event, reply -> reply.system("DC_TICKET_CREATED", ticketChannel.getAsMention()));
        Chatter.serverteam().prefixless("DISCORD_TICKET_NEW", ticketChannel.getName());
    }

    @Override
    public void onGenericComponentInteractionCreate(@NotNull GenericComponentInteractionCreateEvent event) {
        MessageChannel messageChannel = event.getChannel();
        if(messageChannel instanceof TextChannel channel && channel.getParentCategoryIdLong() != 0 && channel.getParentCategoryId().equals(TICKET_CATEGORY) && event.getComponentId().startsWith("close-")) {
            LinkedList<StringBuilder> messages = channel.getIterableHistory().reverse().complete().stream()
                    .filter(message -> !message.getAuthor().isSystem() && !message.getAuthor().isBot())
                    .map(message -> {
                        StringBuilder stringBuilder = new StringBuilder()
                                .append("<t:").append(message.getTimeCreated().toInstant().getEpochSecond()).append("> ")
                                .append("**").append(message.getAuthor().getName()).append("**: ")
                                .append(message.getContentRaw())
                                .append("\n");

                        if(!message.getAttachments().isEmpty()) {
                            message.getAttachments().forEach(attachment -> stringBuilder.append(attachment.getUrl()));
                            stringBuilder.append("\n");
                        }

                        return stringBuilder;
                    })
                    .collect(Collectors.toCollection(LinkedList::new));

            messages.add(new StringBuilder().append("<t:").append(Instant.now().getEpochSecond()).append("> **").append(event.getUser().getName()).append("**: Ticket closed"));

            EmbedBuilder embedBuilder = new EmbedBuilder()
                    .setColor(Color.GREEN)
                    .setTimestamp(Instant.now())
                    .setTitle(event.getChannel().getName());

            User user;
            if(channel.getTopic() != null && !channel.getTopic().isEmpty()) {
                user = event.getJDA().retrieveUserById(channel.getTopic()).complete();
                embedBuilder.setAuthor(user.getName(), null, user.getAvatarUrl());
            } else {
                user = null;
            }

            TextChannel logChannel = event.getGuild().getTextChannelById(TICKET_LOG);
            SplitUtil.split(
                    messages.stream()
                            .map(StringBuilder::toString).collect(Collectors.joining()),
                    2000,
                    SplitUtil.Strategy.NEWLINE,
                    SplitUtil.Strategy.ANYWHERE
            ).stream().map(message -> new MessageCreateBuilder().setEmbeds(embedBuilder.setDescription(message).build()))
                    .forEach(builder -> {
                        MessageCreateData createData = builder.build();
                        logChannel.sendMessage(createData).queue();
                        if (user != null) {
                            user.openPrivateChannel().queue(privateChannel -> privateChannel.sendMessage(createData).queue());
                        }
                    });

            Chatter.serverteam().prefixless("DISCORD_TICKET_CLOSED", channel.getName());
            channel.delete().reason("Closed").queue();
        }
    }

    @Override
    public void onMessageReceived(@NotNull MessageReceivedEvent event) {
        MessageChannel channel = event.getChannel();
        if(
                channel instanceof TextChannel textChannel &&
                textChannel.getParentCategoryIdLong() != 0 &&
                textChannel.getParentCategoryId().equals(TICKET_CATEGORY) &&
                !channel.getId().equals(TICKET_CHANNEL) &&
                !channel.getId().equals(TICKET_LOG)
        ) {
            if(event.getAuthor().isBot())
                return;

            ChatterGroup receivers = new ChatterGroup(Chatter.allStream().filter(player -> player.user().hasPerm(UserPerm.TICKET_LOG)));
            try {
                SteamwarUser user = SteamwarUser.get(Long.parseLong(textChannel.getTopic()));
                if(user != null && !user.perms().contains(UserPerm.TEAM))
                    receivers = new ChatterGroup(receivers, Chatter.of(user));
            } catch(NumberFormatException e) {
                //ignored
            }

            receivers.prefixless("DISCORD_TICKET_MESSAGE", new Message("DISCORD_TICKET_HOVER"), ClickEvent.openUrl(event.getMessage().getJumpUrl()), event.getChannel().getName(), event.getAuthor().getName(), event.getMessage().getContentRaw());
        }
    }
}
