package com.zksy.WaterSupply.PipeNetworkStatistics.service.impl;

import com.zksy.WaterSupply.PipeNetworkStatistics.dto.MetricItemDTO;
import com.zksy.WaterSupply.PipeNetworkStatistics.dto.PipeNetworkStatisticsDashboardDTO;
import com.zksy.WaterSupply.PipeNetworkStatistics.mapper.PipeNetworkStatisticsMapper;
import com.zksy.WaterSupply.PipeNetworkStatistics.service.PipeNetworkStatisticsService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class PipeNetworkStatisticsServiceImpl implements PipeNetworkStatisticsService {
    private static final Set<String> SUPPORTED_TYPES = Set.of("source", "plant", "pumpStation", "pipe", "user");

    @Resource
    private PipeNetworkStatisticsMapper statisticsMapper;

    @Override
    public PipeNetworkStatisticsDashboardDTO getDashboard(String status, Set<String> facilityTypes) {
        validateFacilityTypes(facilityTypes);
        Set<String> types = facilityTypes == null || facilityTypes.isEmpty() ? SUPPORTED_TYPES : facilityTypes;
        PipeNetworkStatisticsDashboardDTO dashboard = new PipeNetworkStatisticsDashboardDTO();
        List<com.zksy.WaterSupply.PipeNetworkStatistics.dto.FacilityStatisticItemDTO> overview = statisticsMapper.selectFacilityOverview(status);
        dashboard.setFacilityOverview((overview == null ? Collections.<com.zksy.WaterSupply.PipeNetworkStatistics.dto.FacilityStatisticItemDTO>emptyList() : overview)
                .stream().filter(item -> types.contains(item.getFacilityType())).collect(Collectors.toList()));
        if (types.contains("pipe")) {
            Map<String, Object> result = zeroSafe(statisticsMapper.selectPipeSummary(status));
            result.put("materialDistribution", list(statisticsMapper.selectPipeMaterialDistribution(status)));
            result.put("diameterDistribution", list(statisticsMapper.selectPipeDiameterDistribution(status)));
            result.put("layingYearDistribution", list(statisticsMapper.selectPipeLayingYearDistribution(status)));
            result.put("pressureDistribution", list(statisticsMapper.selectPipePressureDistribution(status)));
            result.put("statusDistribution", list(statisticsMapper.selectStatusDistribution("pipe", status)));
            dashboard.setPipeNetwork(result);
        }
        if (types.contains("plant")) {
            Map<String, Object> result = zeroSafe(statisticsMapper.selectWaterPlantSummary(status));
            result.put("capacityUtilization", utilization(result));
            result.put("statusDistribution", list(statisticsMapper.selectStatusDistribution("plant", status)));
            result.put("waterSourceTypeDistribution", list(statisticsMapper.selectWaterPlantSourceTypeDistribution(status)));
            dashboard.setWaterPlant(result);
        }
        if (types.contains("pumpStation")) {
            Map<String, Object> result = zeroSafe(statisticsMapper.selectPumpStationSummary(status));
            result.put("statusDistribution", list(statisticsMapper.selectStatusDistribution("pumpStation", status)));
            dashboard.setPumpStation(result);
        }
        if (types.contains("source")) {
            Map<String, Object> result = zeroSafe(statisticsMapper.selectWaterSourceSummary(status));
            result.put("statusDistribution", list(statisticsMapper.selectStatusDistribution("source", status)));
            result.put("sourceTypeDistribution", list(statisticsMapper.selectWaterSourceTypeDistribution(status)));
            result.put("qualityDistribution", list(statisticsMapper.selectWaterSourceQualityDistribution(status)));
            result.put("protectionDistribution", list(statisticsMapper.selectWaterSourceProtectionDistribution(status)));
            dashboard.setWaterSource(result);
        }
        if (types.contains("user")) {
            Map<String, Object> result = zeroSafe(statisticsMapper.selectWaterUserSummary(status));
            result.put("statusDistribution", list(statisticsMapper.selectStatusDistribution("user", status)));
            result.put("userTypeDistribution", list(statisticsMapper.selectWaterUserTypeDistribution(status)));
            result.put("consumptionDistribution", list(statisticsMapper.selectWaterUserConsumptionDistribution(status)));
            dashboard.setWaterUser(result);
        }
        return dashboard;
    }

    private void validateFacilityTypes(Set<String> facilityTypes) {
        if (facilityTypes != null && !SUPPORTED_TYPES.containsAll(facilityTypes)) {
            throw new IllegalArgumentException("不支持的设施类型");
        }
    }

    private Map<String, Object> zeroSafe(Map<String, Object> value) {
        return value == null ? new LinkedHashMap<>() : new LinkedHashMap<>(value);
    }

    private List<MetricItemDTO> list(List<MetricItemDTO> value) {
        return value == null ? Collections.emptyList() : value;
    }

    private BigDecimal utilization(Map<String, Object> values) {
        BigDecimal design = decimal(values.get("designCapacity") == null ? values.get("design_capacity") : values.get("designCapacity"));
        BigDecimal current = decimal(values.get("currentCapacity") == null ? values.get("current_capacity") : values.get("currentCapacity"));
        return design.signum() == 0 ? BigDecimal.ZERO : current.multiply(BigDecimal.valueOf(100)).divide(design, 2, RoundingMode.HALF_UP);
    }

    private BigDecimal decimal(Object value) {
        if (value instanceof BigDecimal) return (BigDecimal) value;
        return value == null ? BigDecimal.ZERO : new BigDecimal(value.toString());
    }
}
