package cn.reghao.tnb.content.app.geo.service;

import cn.reghao.jutil.jdk.serializer.JsonConverter;
import cn.reghao.jutil.jdk.io.TextFile;
import cn.reghao.tnb.common.db.SelectOption;
import cn.reghao.tnb.content.app.geo.db.mapper.CameraPhotoMapper;
import cn.reghao.tnb.content.app.geo.db.mapper.GeoChinaMapper;
import cn.reghao.tnb.content.app.geo.model.po.GeoJson;
import cn.reghao.tnb.content.app.geo.model.vo.AreaCount;
import cn.reghao.tnb.content.app.geo.model.vo.ChartMap;
import cn.reghao.tnb.content.app.geo.model.vo.ChartMapData;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import jakarta.annotation.PostConstruct;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author reghao
 * @date 2025-08-18 22:49:55
 */
@Slf4j
@Service
public class ChartMapService {
    private final GeoChinaMapper geoChinaMapper;
    private final CameraPhotoMapper cameraPhotoMapper;
    private final TextFile textFile = new TextFile();
    private String china3GeoJson = "";

    public ChartMapService(GeoChinaMapper geoChinaMapper, CameraPhotoMapper cameraPhotoMapper) {
        this.geoChinaMapper = geoChinaMapper;
        this.cameraPhotoMapper = cameraPhotoMapper;
    }

    @PostConstruct
    public void load() {
        //china3GeoJson = textFile.readFile("china3.json");
    }

    public List<SelectOption> getAreaNameValue() {
        List<GeoJson> list = geoChinaMapper.findGeoJsonObject();
        return list.stream().map(geoJson -> {
            String name = geoJson.getName();
            int areaCode = geoJson.getAreaCode();
            int deep = geoJson.getDeep();
            String label = String.format("%s-%s", name, deep);
            String value = String.format("%s-%s", areaCode, deep);
            return new SelectOption(label, value);
        }).collect(Collectors.toList());
    }

    public ChartMap getChartMap(int areaCode, int deep) {
        String geoJson = geoChinaMapper.findGeoJson(areaCode, deep);
        if (areaCode == 10 && deep == 3) {
            //geoJson = china3GeoJson;
            return new ChartMap();
        }

        List<AreaCount> areaCountList;
        if (areaCode == 10) {
            areaCountList = cameraPhotoMapper.findAreaCountByGroup("");
        } else {
            areaCountList = cameraPhotoMapper.findAreaCountByGroup(""+areaCode);
        }

        Map<Integer, String> areaMap = getAreaMap(geoJson, deep);
        List<ChartMapData> chartMapDataList = new ArrayList<>();
        areaCountList.forEach(areaCount -> {
            int areaId = areaCount.getAreaCode();
            String areaIdStr = ""+areaId;
            Set<Long> set = Arrays.stream(areaCount.getAlbumIds().split(","))
                    .map(Long::parseLong)
                    .collect(Collectors.toSet());

            if (deep == 3) {
                String areaName = areaMap.get(areaId);
                if (areaName != null) {
                    chartMapDataList.add(new ChartMapData(areaName, set.size()));
                }
            } else {
                for (int code : areaMap.keySet()) {
                    String codeStr = ""+code;
                    if (areaIdStr.startsWith(codeStr)) {
                        String areaName = areaMap.get(code);
                        chartMapDataList.add(new ChartMapData(areaName, set.size()));
                    } else {
                        // log.error("{} not matched", areaIdStr);
                    }
                }
            }
        });

        return new ChartMap(geoJson, chartMapDataList);
    }

    private Map<Integer, String> getAreaMap(String geoJson, int deep) {
        Map<Integer, String> map = new HashMap<>();
        JsonObject jsonObject = JsonConverter.jsonToJsonElement(geoJson).getAsJsonObject();
        for (JsonElement jsonElement : jsonObject.get("features").getAsJsonArray()) {
            JsonObject propertiesObject = jsonElement.getAsJsonObject().get("properties").getAsJsonObject();
            int adcode = propertiesObject.get("adcode").getAsInt();
            String name = propertiesObject.get("name").getAsString();
            if (deep == 3) {
                map.put(adcode, name);
            } else if (deep == 2) {
                String adcodeStr = (""+adcode).substring(0, 4);
                map.put(Integer.parseInt(adcodeStr), name);
            } else if (deep == 1) {
                String adcodeStr = (""+adcode).substring(0, 2);
                map.put(Integer.parseInt(adcodeStr), name);
            }
        }

        return map;
    }
}
