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.OrgStatisticsVO;
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 PortalStatisticsOrgTableManService extends BaseService {

    private final PortalStatisticsService portalStatisticsService;

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

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

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

        return result;
    }

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

        summary.put("totalOrgs", stats.stream().map(OrgStatisticsVO::getOrgId).distinct().count());

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

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

        summary.put("topOrgs", topOrgs);

        return summary;
    }

    private List<Map<String, Object>> convertToOrgStats(List<OrgStatisticsVO> stats) {
        Map<String, Map<String, Object>> orgStats = new LinkedHashMap<>();

        for (OrgStatisticsVO stat : stats) {
            Map<String, Object> orgStat = orgStats.computeIfAbsent(stat.getOrgId(), k -> new LinkedHashMap<>());
            orgStat.put("orgName", Optional.ofNullable(stat.getOrgName()).orElse("N/A"));
            orgStat.put("totalRequests", ((Long) orgStat.getOrDefault("totalRequests", 0L)) + stat.getRequestCount());
            orgStat.put("totalFailures", ((Long) orgStat.getOrDefault("totalFailures", 0L)) + stat.getFailureCount());
        }

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