package ru.soune.nocopy.service.statistic;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import ru.soune.nocopy.dto.statistic.IncomeStatisticResponse;
import ru.soune.nocopy.repository.ReferralJpaRepository;
import ru.soune.nocopy.util.PercentileCalculator;

import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class IncomeStatisticService {
    private final ReferralJpaRepository referralRepository;

    private static final int PERCENTILE_5 = 5;

    private static final int PERCENTILE_50 = 50;

    private static final int PERCENTILE_95 = 95;

    public IncomeStatisticResponse getIncomeStatistics() {
        Long totalIncome = referralRepository.getTotalIncome();
        Long totalAvailable = referralRepository.getTotalAvailableIncome();
        Long totalHold = referralRepository.getTotalHoldBalance();

        List<Object[]> incomeData = referralRepository.getIncomePerUser();
        List<Long> incomeValues = extractIncomeValues(incomeData);

        PercentileCalculator.PercentilesResult incomePercentiles =
                PercentileCalculator.calculatePercentiles(incomeValues, PERCENTILE_5, PERCENTILE_50,
                        PERCENTILE_95);

        return IncomeStatisticResponse.builder()
                .totalIncome(totalIncome != null ? totalIncome : 0L)
                .totalAvailable(totalAvailable != null ? totalAvailable : 0L)
                .totalHold(totalHold != null ? totalHold : 0L)
                .incomePerUser(new IncomeStatisticResponse.Percentiles(
                        incomePercentiles.getP5() != null ? incomePercentiles.getP5() : 0L,
                        incomePercentiles.getP50() != null ? incomePercentiles.getP50() : 0L,
                        incomePercentiles.getP95() != null ? incomePercentiles.getP95() : 0L
                ))
                .build();
    }

    private List<Long> extractIncomeValues(List<Object[]> data) {
        return data.stream()
                .map(row -> row[1] != null ? ((Number) row[1]).longValue() : 0L)
                .filter(value -> value > 0)
                .collect(Collectors.toList());
    }
}
