package dev.nincodedo.ninbot.components.channel.thread;

import dev.nincodedo.ninbot.common.BaseListenerAdapter;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.ThreadChannel;
import net.dv8tion.jda.api.events.channel.update.ChannelUpdateArchiveTimestampEvent;
import net.dv8tion.jda.api.events.channel.update.ChannelUpdateArchivedEvent;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;

import java.time.OffsetDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

@Slf4j
@Component
public class ThreadUnarchivedAnnouncement extends BaseListenerAdapter {

    @Getter
    private final List<String> threadChannelIdList = new ArrayList<>();

    @Override
    public void onChannelUpdateArchived(@NotNull ChannelUpdateArchivedEvent event) {
        var threadChannel = (ThreadChannel) event.getChannel();
        if (!threadChannel.isPublic()) {
            return;
        }
        if (Boolean.TRUE.equals(event.getOldValue()) && Boolean.FALSE.equals(event.getNewValue())) {
            threadChannel.retrieveMessageById(threadChannel.getLatestMessageId()).queue(checkMessage(threadChannel));
        }
    }

    Consumer<Message> checkMessage(ThreadChannel threadChannel) {
        return message -> {
            var amount = 10;
            var unit = ChronoUnit.SECONDS;
            if (message.getTimeCreated().isAfter(OffsetDateTime.now().minus(amount, unit))) {
                var threadId = threadChannel.getId();
                log.trace("Thread {} unarchived with a recent message", threadId);
                synchronized (threadChannelIdList) {
                    determineThreadAnnouncement(threadChannel, threadId);
                }
            }
        };
    }

    @Override
    public void onChannelUpdateArchiveTimestamp(@NotNull ChannelUpdateArchiveTimestampEvent event) {
        var threadChannel = (ThreadChannel) event.getChannel();
        if (!threadChannel.isPublic()) {
            return;
        }
        var minutesHighThreshold = threadChannel.getAutoArchiveDuration().getMinutes() + 1;
        if (event.getOldValue() != null && event.getOldValue()
                .isBefore(OffsetDateTime.now().minus(minutesHighThreshold, ChronoUnit.MINUTES))) {
            var threadId = threadChannel.getId();
            log.trace("Thread {} archive timestamp updated from {} to {}", threadId, event.getOldValue(),
                    event.getNewValue());
            synchronized (threadChannelIdList) {
                determineThreadAnnouncement(threadChannel, threadId);
            }
        }
    }

    private void determineThreadAnnouncement(ThreadChannel threadChannel, String threadId) {
        if (threadChannelIdList.contains(threadId)) {
            log.trace("Thread {} meets both criteria, announcing revival", threadId);
            announceThreadRevival(threadChannel);
            threadChannelIdList.remove(threadId);
        } else {
            log.trace("Thread {} meets one criteria, adding to monitoring list", threadId);
            threadChannelIdList.add(threadId);
        }
    }

    private void announceThreadRevival(ThreadChannel threadChannel) {
        var parentChannel = threadChannel.getParentMessageChannel();
        var threadChannelMention = threadChannel.getAsMention();
        parentChannel.sendMessageFormat(resource("threadunarchiveannouncement.threadrevived"), threadChannelMention)
                .queue();
    }
}

@@ -630,24 +630,155 @@
 .util.List;%0A
+import java.util.concurrent.Executors;%0Aimport java.util.concurrent.ScheduledExecutorService;%0Aimport java.util.concurrent.TimeUnit;%0A
 import java.
@@ -976,16 +976,117 @@
 ist%3C%3E();
+%0A    private ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
 %0A%0A    @O
@@ -1950,65 +1950,8 @@
 d);%0A
-                synchronized (threadChannelIdList) %7B%0A    
     
@@ -2020,26 +2020,8 @@
 d);%0A
-                %7D%0A
     
@@ -2754,61 +2754,8 @@
 ));%0A
-            synchronized (threadChannelIdList) %7B%0A    
     
@@ -2812,38 +2812,24 @@
  threadId);%0A
-            %7D%0A
         %7D%0A  
@@ -2922,24 +2922,114 @@
 threadId) %7B%0A
+        boolean isDelayedRemove = false;%0A        synchronized (threadChannelIdList) %7B%0A    
         if (
@@ -3066,24 +3066,28 @@
 hreadId)) %7B%0A
+    
             
@@ -3172,16 +3172,20 @@
         
+    
 announce
@@ -3218,32 +3218,36 @@
 l);%0A            
+  
+  
 threadChannelIdL
@@ -3276,16 +3276,20 @@
         
+    
 %7D else %7B
@@ -3289,16 +3289,20 @@
  else %7B%0A
+    
         
@@ -3389,32 +3389,36 @@
 d);%0A            
+  
+  
 threadChannelIdL
@@ -3428,32 +3428,231 @@
 .add(threadId);%0A
+                isDelayedRemove = true;%0A            %7D%0A        %7D%0A        if (isDelayedRemove) %7B%0A            executorService.schedule(() -%3E threadChannelIdList.remove(threadId), 10, TimeUnit.SECONDS);%0A
         %7D%0A    %7D%0A

Fix thread reviving announcements