package com.izouma.nineth.service;

import cn.hutool.core.collection.CollUtil;
import com.izouma.nineth.domain.Order;
import com.izouma.nineth.domain.User;
import com.izouma.nineth.enums.AuthorityName;
import com.izouma.nineth.enums.CollectionSource;
import com.izouma.nineth.enums.OrderStatus;
import com.izouma.nineth.repo.OrderRepo;
import com.izouma.nineth.repo.UserRepo;
import com.izouma.nineth.security.Authority;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class StatisticService {

    private UserRepo  userRepo;
    private OrderRepo orderRepo;

    public Map<String, Object> total() {
        Map<String, Object> total = new HashMap<>();

        long user = userRepo.countAllByAuthoritiesContainsAndDelFalse(Authority.get(AuthorityName.ROLE_USER));
        total.put("userNum", user);

        List<Order> orders = orderRepo.findAllByStatus(OrderStatus.FINISH);
        Map<CollectionSource, List<Order>> orderMap = orders.stream().collect(Collectors.groupingBy(Order::getSource));
        List<Order> officialOrders = orderMap.get(CollectionSource.OFFICIAL);
        List<Order> transferOrders = orderMap.get(CollectionSource.TRANSFER);
        total.put("officialNum", officialOrders.size());
        total.put("transferNum", transferOrders.size());

        BigDecimal officialPrice = officialOrders.stream()
                .map(Order::getTotalPrice)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal transferPrice = transferOrders.stream()
                .map(Order::getTotalPrice)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        total.put("officialPrice", officialPrice);
        total.put("transferPrice", transferPrice);

        return total;
    }

    /*
    按天
     */
    public Map<String, Long> userTrend(int day) {
        LocalDateTime date = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        LocalDateTime start = date.minusDays(day);
        List<User> users = userRepo.findAllByCreatedAtIsAfterAndAuthoritiesContains(start, Authority.get(AuthorityName.ROLE_USER));
        return users.stream().collect(Collectors.groupingBy(
                item -> DateTimeFormatter.ofPattern("yyyy-MM-dd").format(item.getCreatedAt()), Collectors.counting()));
    }

    public Map<String, Map<String, Long>> orderNumTrend(int day) {
        LocalDateTime date = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        LocalDateTime start = date.minusDays(day);
        List<Order> orders = orderRepo.findAllByPayTimeIsAfter(start);
        Map<CollectionSource, List<Order>> orderMap = orders.stream().collect(Collectors.groupingBy(Order::getSource));
        Map<String, Long> official = orderMap.get(CollectionSource.OFFICIAL).stream().collect(Collectors.groupingBy(
                item -> DateTimeFormatter.ofPattern("yyyy-MM-dd").format(item.getPayTime()), Collectors.counting()));
        Map<String, Long> transfer = null;
        if (CollUtil.isNotEmpty(orderMap.get(CollectionSource.TRANSFER))) {
            transfer = orderMap.get(CollectionSource.TRANSFER).stream().collect(Collectors.groupingBy(
                    item -> DateTimeFormatter.ofPattern("yyyy-MM-dd")
                            .format(item.getPayTime()), Collectors.counting()));
        }

        Map<String, Map<String, Long>> trend = new HashMap<>();
        trend.put("official", official);
        trend.put("transfer", transfer);
        return trend;
    }

    public Map<String, Map<String, BigDecimal>> orderPriceTrend(int day) {
        LocalDateTime date = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        LocalDateTime start = date.minusDays(day);
        List<Order> orders = orderRepo.findAllByPayTimeIsAfter(start);
        Map<CollectionSource, List<Order>> orderMap = orders.stream().collect(Collectors.groupingBy(Order::getSource));
        Map<String, BigDecimal> official = orderMap.get(CollectionSource.OFFICIAL)
                .stream()
                .collect(Collectors.groupingBy(
                        item -> DateTimeFormatter.ofPattern("yyyy-MM-dd")
                                .format(item.getPayTime()), Collectors.mapping(Order::getTotalPrice,
                                Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));

        Map<String, BigDecimal> transfer = null;
        if (CollUtil.isNotEmpty(orderMap.get(CollectionSource.TRANSFER))) {
            transfer = orderMap.get(CollectionSource.TRANSFER)
                    .stream()
                    .collect(Collectors.groupingBy(
                            item -> DateTimeFormatter.ofPattern("yyyy-MM-dd")
                                    .format(item.getPayTime()), Collectors.mapping(Order::getTotalPrice,
                                    Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));
        }

        Map<String, Map<String, BigDecimal>> trend = new HashMap<>();
        trend.put("official", official);
        trend.put("transfer", transfer);
        return trend;
    }
}
