package com.eactive.eai.rms.onl.apim.portalstatistics;

import com.eactive.eai.rms.common.base.BaseService;
import com.eactive.eai.rms.data.entity.onl.apim.portalstatistics.AppStatisticsVO;
import com.eactive.eai.rms.data.entity.onl.apim.portalstatistics.PortalStatisticsService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional(transactionManager = "transactionManagerForEMS")
public class PortalStatisticsAppTableManService extends BaseService {

    private final PortalStatisticsService portalStatisticsService;

    public PortalStatisticsAppTableManService(PortalStatisticsService portalStatisticsService) {
        this.portalStatisticsService = portalStatisticsService;
    }

    public Map<String, Object> selectStatisticsList(LocalDate startDate, LocalDate endDate) {
        List<AppStatisticsVO> stats = portalStatisticsService.getDetailedAppStatistics(startDate, endDate);

        Map<String, Object> result = new HashMap<>();
        result.put("summary", calculateSummary(stats));
        result.put("appStats", convertToAppStats(stats));

        return result;
    }

    private Map<String, Object> calculateSummary(List<AppStatisticsVO> stats) {
        Map<String, Object> summary = new HashMap<>();

        summary.put("totalApps", stats.stream().map(AppStatisticsVO::getAppId).distinct().count());

        long totalRequests = stats.stream().mapToLong(AppStatisticsVO::getRequestCount).sum();
        long totalFailures = stats.stream().mapToLong(AppStatisticsVO::getFailureCount).sum();
        summary.put("totalRequests", totalRequests);
        summary.put("totalFailures", totalFailures);
        summary.put("overallSuccessRate", totalRequests > 0 ? (double) (totalRequests - totalFailures) / totalRequests * 100 : 0);

        List<String> topApps = stats.stream()
                .collect(Collectors.groupingBy(
                        app -> Optional.ofNullable(app.getAppName()).orElse("N/A"),
                        Collectors.summingLong(app -> Optional.ofNullable(app.getRequestCount()).orElse(0L))
                ))
                .entrySet().stream()
                .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
                .limit(5)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());

        summary.put("topApps", topApps);

        return summary;
    }

    private List<Map<String, Object>> convertToAppStats(List<AppStatisticsVO> stats) {
        Map<String, Map<String, Object>> appStats = new LinkedHashMap<>();

        for (AppStatisticsVO stat : stats) {
            Map<String, Object> appStat = appStats.computeIfAbsent(stat.getAppId(), k -> new LinkedHashMap<>());
            appStat.put("appName", Optional.ofNullable(stat.getAppName()).orElse("N/A"));
            appStat.put("totalRequests", ((Long) appStat.getOrDefault("totalRequests", 0L)) + stat.getRequestCount());
            appStat.put("totalFailures", ((Long) appStat.getOrDefault("totalFailures", 0L)) + stat.getFailureCount());
        }

        return appStats.values().stream()
                .map(appStat -> {
                    long totalRequests = (Long) appStat.get("totalRequests");
                    long totalFailures = (Long) appStat.get("totalFailures");
                    double successRate = totalRequests > 0 ? (double) (totalRequests - totalFailures) / totalRequests * 100 : 0;
                    appStat.put("successRate", String.format("%.2f", successRate));
                    return appStat;
                })
                .collect(Collectors.toList());
    }
}