package com.izouma.nineth.web;

import com.izouma.nineth.service.CacheService;
import com.izouma.nineth.service.StatisticService;
import com.izouma.nineth.utils.SecurityUtils;
import lombok.AllArgsConstructor;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.YearMonth;
import java.util.Map;

@RestController
@RequestMapping("/statistic")
@AllArgsConstructor
public class StatisticController {
    private StatisticService statisticService;
    private CacheService     cacheService;

    @GetMapping("/total")
    @Cacheable("total")
    @PreAuthorize("hasAnyRole('ADMIN','COMPANY','ORDERINFO')")
    public Map<String, Object> total() {
        return statisticService.total(SecurityUtils.getAuthenticatedUser().getId());
    }

    @GetMapping("/userTrend")
    @Cacheable("userTrend")
    @PreAuthorize("hasAnyRole('ADMIN','ORDERINFO')")
    public Map<String, Long> userTrend(int day) {
        return statisticService.userTrend(day);
    }

    @GetMapping("/userTrendV2")
    @Cacheable(value = "userTrendV2", key = "#yearMonth")
    @PreAuthorize("hasAnyRole('ADMIN','ORDERINFO')")
    public Map<String, Long> userTrendV2(String yearMonth) {
        return statisticService.userTrendV2(yearMonth);
    }

    @GetMapping("/orderNumTrend")
    @Cacheable("orderNumTrend")
    @PreAuthorize("hasAnyRole('ADMIN','COMPANY','ORDERINFO')")
    public Map<String, Map<String, Long>> orderNumTrend(int day) {
        return statisticService.orderNumTrend(day, SecurityUtils.getAuthenticatedUser().getId());
    }

    @GetMapping("/orderPriceTrend")
    @Cacheable("orderPriceTrend")
    @PreAuthorize("hasAnyRole('ADMIN','COMPANY','ORDERINFO')")
    public Map<String, Map<String, BigDecimal>> orderPriceTrend(int day) {
        return statisticService.orderPriceTrend(day, SecurityUtils.getAuthenticatedUser().getId());
    }

    @GetMapping("/orderPriceTrendV2")
    @Cacheable(value = "orderPriceTrendV2", key = "#yearMonth")
    @PreAuthorize("hasAnyRole('ADMIN','COMPANY','ORDERINFO')")
    public Map<String, BigDecimal> orderPriceTrendV2(String yearMonth) {
        return statisticService.orderPriceTrendV2(yearMonth, SecurityUtils.getAuthenticatedUser().getId());
    }

    @GetMapping("/top")
    @CachePut(value = "top", key = "#month")
    @PreAuthorize("hasAnyRole('ADMIN','ORDERINFO')")
    public String top(int year, int month) {
        LocalDateTime start = LocalDateTime.of(year, month, 1, 0, 0, 0);
        LocalDateTime end = start.plusMonths(1).minusSeconds(1);
        return statisticService.top(start, end, 50);
    }

    @GetMapping("/weekTop")
    @Cacheable("weekTop")
    public String weekTop() {
        LocalDate now = LocalDate.now();
        LocalDate endDate = now.minusDays(now.getDayOfWeek().getValue());
        LocalDateTime start = LocalDateTime.of(endDate.minusDays(6), LocalTime.MIN);
        return statisticService.top(start, LocalDateTime.of(endDate, LocalTime.MAX), 50);
    }

    @Scheduled(fixedRate = 120000)
    public void clearTop() {
        int monthValue = LocalDate.now().getMonthValue();
        cacheService.clearTop(monthValue);
    }

    @PreAuthorize("hasRole('ADMIN')")
    @GetMapping("/clearWeekTop")
    public void clearWeekTop() {
        cacheService.clearWeekTop();
    }

    @PreAuthorize("hasRole('ADMIN')")
    @GetMapping("/clearUser")
    public void clearUser() {
        cacheService.clearUser();
    }
}
