package com.mingzuozhibi.modules.group;

import com.mingzuozhibi.modules.disc.Disc;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Stream;

import static com.mingzuozhibi.commons.utils.MyTimeUtils.toInstant;
import static java.util.Collections.emptyList;
import static java.util.Comparator.*;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toCollection;

@Service
public class DiscGroupService {

    @Autowired
    private DiscGroupRepository discGroupRepository;

    @Transactional
    public Set<String> findNeedUpdateAsins() {
        return findNeedUpdateDiscs()
            .map(Disc::getAsin)
            .collect(toCollection(LinkedHashSet::new));
    }

    private Stream<Disc> findNeedUpdateDiscs() {
        return discGroupRepository.findActiveDiscGroups().stream()
            .flatMap(discGroup -> discGroup.getDiscs().stream());
    }

    @Transactional
    public Set<String> findNeedUpdateAsinsSorted() {
        Map<String, List<Disc>> map = findNeedUpdateDiscs()
            .collect(groupingBy(updateBeforeTarget()));
        Stream<Disc> before = map.getOrDefault("before", emptyList()).stream()
            .sorted(comparing(Disc::getUpdateTime, nullsLast(naturalOrder())));
        Stream<Disc> normal = map.getOrDefault("normal", emptyList()).stream();
        return Stream.concat(before, normal)
            .map(Disc::getAsin)
            .collect(toCollection(LinkedHashSet::new));
    }

    private Function<Disc, String> updateBeforeTarget() {
        LocalDateTime target = LocalDateTime.now().minusHours(9);
        return disc -> disc.getUpdateTime() == null || disc.getUpdateTime().isBefore(target)
            ? "before"
            : "normal";
    }

    @Transactional
    public Set<Disc> findNeedRecordDiscs() {
        LocalDate target = LocalDate.now().minusDays(7);
        return findNeedUpdateDiscs()
            .filter(disc -> disc.getReleaseDate().isAfter(target))
            .collect(toCollection(LinkedHashSet::new));
    }

    @Transactional
    public void updateGroupModifyTime() {
        Comparator<Disc> comparator = comparing(Disc::getUpdateTime, nullsFirst(naturalOrder()));
        discGroupRepository.findByEnabled(true).forEach(discGroup -> {
            discGroup.getDiscs().stream().max(comparator).ifPresent(disc -> {
                discGroup.setModifyTime(toInstant(disc.getUpdateTime()));
            });
        });
    }

}

@@ -330,17 +330,96 @@
 va.util.
-*
+LinkedHashSet;%0Aimport java.util.List;%0Aimport java.util.Map;%0Aimport java.util.Set
 ;%0Aimport
@@ -1353,16 +1353,24 @@
 %3E map = 
+groupBy(
 findNeed
@@ -1382,28 +1382,27 @@
 eDiscs()
-%0A   
+);%0A
         
  .collec
@@ -1397,82 +1397,58 @@
     
- .collect(groupingBy(updateBeforeTarget()));%0A        Stream%3CDisc%3E before =
+Set%3CString%3E asins = new LinkedHashSet%3C%3E();%0A       
  map
@@ -1462,22 +1462,22 @@
 efault(%22
-before
+list_1
 %22, empty
@@ -1571,17 +1571,16 @@
 der())))
-;
 %0A       
@@ -1584,29 +1584,64 @@
     
-Stream%3CDisc%3E normal =
+    .forEach(disc -%3E asins.add(disc.getAsin()));%0A       
  map
@@ -1655,22 +1655,22 @@
 efault(%22
-normal
+list_2
 %22, empty
@@ -1680,95 +1680,170 @@
 t())
-.stream();%0A        return Stream.concat(before, normal)%0A            .map(Disc::
+%0A            .forEach(disc -%3E asins.add(disc.getAsin()));%0A        map.getOrDefault(%22list_3%22, emptyList())%0A            .forEach(disc -%3E asins.add(disc.
 getAsin
-)
+()));
 %0A   
@@ -1851,120 +1851,161 @@
     
-    .collect(toCollection(LinkedHashSet::new));%0A    %7D%0A%0A    private Function%3CDisc, String%3E updateBeforeTarget() %7B
+return asins;%0A    %7D%0A%0A    private Map%3CString, List%3CDisc%3E%3E groupBy(Stream%3CDisc%3E discs) %7B%0A        LocalDateTime list_1 = LocalDateTime.now().minusHours(12);
 %0A   
@@ -2023,22 +2023,22 @@
 ateTime 
-target
+list_2
  = Local
@@ -2067,9 +2067,9 @@
 urs(
-9
+8
 );%0A 
@@ -2079,138 +2079,438 @@
     
-return disc -%3E disc.getUpdateTime() == null %7C%7C disc.getUpdateTime().isBefore(target)%0A            ? %22before%22%0A            : %22normal%22
+Function%3CDisc, String%3E function = disc -%3E %7B%0A            if (disc.getUpdateTime() == null)%0A                return %22list_1%22;%0A            if (disc.getUpdateTime().isBefore(list_1))%0A                return %22list_1%22;%0A            if (disc.getUpdateTime().isBefore(list_2)) %7B%0A                return %22list_2%22;%0A            %7D else %7B%0A                return %22list_3%22;%0A            %7D%0A        %7D;%0A        return discs.collect(groupingBy(function))
 ;%0A  
@@ -2867,106 +2867,8 @@
 ) %7B%0A
-        Comparator%3CDisc%3E comparator = comparing(Disc::getUpdateTime, nullsFirst(naturalOrder()));%0A
     
@@ -2919,21 +2919,17 @@
 forEach(
-discG
+g
 roup -%3E 
@@ -2938,29 +2938,25 @@
             
-discG
+g
 roup.getDisc
@@ -2971,24 +2971,106 @@
 am()
-.max(comparator)
+%0A                .max(comparing(Disc::getUpdateTime, nullsFirst(naturalOrder())))%0A                
 .ifP
@@ -3098,29 +3098,29 @@
             
-discG
+    g
 roup.setModi
@@ -3156,24 +3156,28 @@
 teTime()));%0A
+    
             

update sorted asins