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

import com.zksy.WaterSupply.WaterPipeInfo.service.IWaterPipeInfoService;
import com.zksy.WaterSupply.WaterPlantInfo.service.IWaterPlantInfoService;
import com.zksy.WaterSupply.WaterPumpStation.service.IWaterPumpStationService;
import com.zksy.WaterSupply.WaterSourceInfo.service.IWaterSourceInfoService;
import com.zksy.WaterSupply.WaterSupplyGisMap.dto.GisFeatureCollectionDTO;
import com.zksy.WaterSupply.WaterSupplyGisMap.dto.GisFeatureDTO;
import com.zksy.WaterSupply.WaterSupplyGisMap.dto.GisOverviewItemDTO;
import com.zksy.WaterSupply.WaterSupplyGisMap.mapper.WaterSupplyGisMapMapper;
import com.zksy.WaterSupply.WaterSupplyGisMap.service.WaterSupplyGisMapService;
import com.zksy.WaterSupply.WaterUserInfo.service.IWaterUserInfoService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Service
public class WaterSupplyGisMapServiceImpl implements WaterSupplyGisMapService {
    private static final Set<String> SUPPORTED_TYPES = Set.of("source", "plant", "pumpStation", "pipe", "user");
    private static final Map<String, String> TYPE_NAMES = Map.of("source", "水源地", "plant", "水厂", "pumpStation", "泵站", "pipe", "供水管网", "user", "大用水户");

    @Resource private WaterSupplyGisMapMapper mapper;
    @Resource private IWaterSourceInfoService sourceService;
    @Resource private IWaterPlantInfoService plantService;
    @Resource private IWaterPumpStationService pumpStationService;
    @Resource private IWaterPipeInfoService pipeService;
    @Resource private IWaterUserInfoService userService;

    @Override
    public GisFeatureCollectionDTO getFeatures(Set<String> types) {
        validateTypes(types);
        Set<String> selected = types == null || types.isEmpty() ? SUPPORTED_TYPES : types;
        GisFeatureCollectionDTO collection = new GisFeatureCollectionDTO();
        if (selected.contains("source")) addPointFeatures(collection, "source", mapper.selectSourceFeatures());
        if (selected.contains("plant")) addPointFeatures(collection, "plant", mapper.selectPlantFeatures());
        if (selected.contains("pumpStation")) addPointFeatures(collection, "pumpStation", mapper.selectPumpStationFeatures());
        if (selected.contains("pipe")) addPipeFeatures(collection, mapper.selectPipeFeatures());
        if (selected.contains("user")) addPointFeatures(collection, "user", mapper.selectUserFeatures());
        return collection;
    }

    @Override
    public Object getDetail(String facilityType, Long id) {
        if (!SUPPORTED_TYPES.contains(facilityType)) throw new IllegalArgumentException("不支持的设施类型：" + facilityType);
        switch (facilityType) {
            case "source": return sourceService.getById(id);
            case "plant": return plantService.getById(id);
            case "pumpStation": return pumpStationService.getById(id);
            case "pipe": return pipeService.getById(id);
            default: return userService.getById(id);
        }
    }

    @Override
    public List<GisOverviewItemDTO> getOverview() {
        List<GisOverviewItemDTO> rows = mapper.selectOverview();
        if (rows == null || rows.isEmpty()) return Collections.emptyList();
        GisOverviewItemDTO total = new GisOverviewItemDTO();
        total.setFacilityType("total");
        total.setFacilityTypeName("合计");
        total.setTotalCount(rows.stream().mapToLong(item -> item.getTotalCount() == null ? 0 : item.getTotalCount()).sum());
        total.setGeoCompleteCount(rows.stream().mapToLong(item -> item.getGeoCompleteCount() == null ? 0 : item.getGeoCompleteCount()).sum());
        total.setGeoMissingCount(rows.stream().mapToLong(item -> item.getGeoMissingCount() == null ? 0 : item.getGeoMissingCount()).sum());
        List<GisOverviewItemDTO> result = new ArrayList<>(rows);
        result.add(total);
        return result;
    }

    @Override
    public GisFeatureDTO toPipeFeature(Map<String, Object> row) {
        GisFeatureDTO feature = baseFeature("pipe", row);
        Map<String, Object> geometry = new LinkedHashMap<>();
        geometry.put("type", "LineString");
        List<List<BigDecimal>> coordinates = new ArrayList<>();
        coordinates.add(List.of(decimal(row, "startLongitude", "start_longitude"), decimal(row, "startLatitude", "start_latitude")));
        coordinates.add(List.of(decimal(row, "endLongitude", "end_longitude"), decimal(row, "endLatitude", "end_latitude")));
        geometry.put("coordinates", coordinates);
        feature.setGeometry(geometry);
        return feature;
    }

    private void addPointFeatures(GisFeatureCollectionDTO collection, String type, List<Map<String, Object>> rows) {
        if (rows == null) return;
        for (Map<String, Object> row : rows) {
            GisFeatureDTO feature = baseFeature(type, row);
            Map<String, Object> geometry = new LinkedHashMap<>();
            geometry.put("type", "Point");
            geometry.put("coordinates", List.of(decimal(row, "longitude"), decimal(row, "latitude")));
            feature.setGeometry(geometry);
            collection.getFeatures().add(feature);
        }
    }

    private void addPipeFeatures(GisFeatureCollectionDTO collection, List<Map<String, Object>> rows) {
        if (rows != null) for (Map<String, Object> row : rows) collection.getFeatures().add(toPipeFeature(row));
    }

    private GisFeatureDTO baseFeature(String type, Map<String, Object> row) {
        GisFeatureDTO feature = new GisFeatureDTO();
        Object id = value(row, "id");
        feature.setId(type + ":" + id);
        Map<String, Object> properties = new LinkedHashMap<>();
        properties.put("facilityType", type);
        properties.put("facilityTypeName", TYPE_NAMES.get(type));
        properties.put("id", id);
        properties.put("code", value(row, "code"));
        properties.put("name", value(row, "name"));
        properties.put("status", value(row, "status"));
        properties.put("location", value(row, "location"));
        feature.setProperties(properties);
        return feature;
    }

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

    private Object value(Map<String, Object> row, String... keys) {
        for (String key : keys) if (row.containsKey(key)) return row.get(key);
        return null;
    }

    private BigDecimal decimal(Map<String, Object> row, String... keys) {
        Object value = value(row, keys);
        return value instanceof BigDecimal ? (BigDecimal) value : new BigDecimal(value.toString());
    }
}
