package com.ylx.massage.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ylx.common.config.AmapConfig;
import com.ylx.common.core.domain.R;
import com.ylx.common.exception.ServiceException;
import com.ylx.common.utils.http.HttpUtils;
import com.ylx.massage.domain.Area;
import com.ylx.massage.domain.dto.CoordinateDTO;
import com.ylx.massage.domain.vo.*;
import com.ylx.massage.mapper.AreaMapper;
import com.ylx.massage.service.AreaService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service("areaService")
public class AreaServiceImpl extends ServiceImpl<AreaMapper, Area> implements AreaService {

    @Resource
    private AmapConfig amapConfig;

    private static final String AMAP_URL_PATTERN = "https://restapi.amap.com/v3/geocode/regeo?key=%s&location=%s,%s";

    private static final String AMAP_SUCCESS_STATUS = "1";
    private static final String ERROR_MSG_API_KEY_MISSING = "配置文件中未找到或 app.amap-api-key 为空";
    private static final String ERROR_MSG_LOCATION_FAILED = "获取地理位置异常";
    private static final String ERROR_MSG_CITY_NOT_FOUND = "城市数据不存在";
    private static final int MAX_QUERY_RESULTS = 1;

    /**
     * 一次性查询所有区域，内存构建树形结构
     */
    @Override
    public List<AreaTreeNode> getAreaTree() {
        // 1. 只查询需要的字段，减少数据传输与内存占用（核心优化）
        List<Area> areaList = this.list(Wrappers.lambdaQuery(Area.class)
                .select(Area::getId, Area::getCode, Area::getName, Area::getParentCode, Area::getLevel)
        );

        // 2. 转树形节点（流式处理）
        List<AreaTreeNode> allNodes = areaList.stream()
                .map(area -> {
                    AreaTreeNode node = new AreaTreeNode();
                    node.setId(area.getId());
                    node.setCode(area.getCode());
                    node.setName(area.getName());
                    node.setParentCode(area.getParentCode());
                    node.setLevel(area.getLevel());
                    node.setChildren(new ArrayList<>()); // 预先初始化，避免空指针
                    return node;
                })
                .collect(Collectors.toList());

        // 3. 构建 code -> node 映射（O(1) 快速查找，性能提升巨大）
        Map<String, AreaTreeNode> nodeMap = allNodes.stream()
                .collect(Collectors.toMap(AreaTreeNode::getCode, node -> node));

        // 4. 组装父子关系（单循环，O(n) 最优复杂度）
        for (AreaTreeNode node : allNodes) {
            String parentCode = node.getParentCode();
            AreaTreeNode parentNode = nodeMap.get(parentCode);
            if (parentNode != null) {
                parentNode.getChildren().add(node);
            }
        }

        // 5. 只返回顶级节点（parentCode = 0）
        return allNodes.stream()
                .filter(node -> "0".equals(node.getParentCode()))
                .collect(Collectors.toList());
    }

    @Override
    public CityInfoVo getCityInfoByCoordinates(CoordinateDTO dto) {
        // 参数验证
        validateCoordinates(dto);

        // 获取API Key
        String amapKey = amapConfig.getApiKey();
        if (StrUtil.isEmpty(amapKey)) {
            log.error(ERROR_MSG_API_KEY_MISSING);
            throw new ServiceException(ERROR_MSG_API_KEY_MISSING);
        }

        try {
            // 调用高德API
            String url = String.format(AMAP_URL_PATTERN, amapKey, dto.getLongitude(), dto.getLatitude());
            String response = HttpUtils.sendGet(url);

            // 解析响应
            AmapRegeoVo amapResponse = parseAmapResponse(response);

            // 获取城市信息
            return getCityInfo(amapResponse);
        } catch (Exception e) {
            log.error("获取城市信息失败", e);
            throw new ServiceException(e.getMessage());
        }
    }

    private void validateCoordinates(CoordinateDTO dto) {
        if (dto == null) {
            throw new IllegalArgumentException("坐标信息不能为空");
        }
        if (dto.getLongitude() < -180 || dto.getLongitude() > 180) {
            throw new IllegalArgumentException("经度必须在-180到180之间");
        }
        if (dto.getLatitude() < -90 || dto.getLatitude() > 90) {
            throw new IllegalArgumentException("纬度必须在-90到90之间");
        }
    }

    private AmapRegeoVo parseAmapResponse(String response) {
        if (StrUtil.isEmpty(response)) {
            throw new ServiceException(ERROR_MSG_LOCATION_FAILED);
        }

        AmapRegeoVo vo = JSONObject.parseObject(response, AmapRegeoVo.class);
        if (vo == null || !AMAP_SUCCESS_STATUS.equals(vo.getStatus())) {
            throw new ServiceException(ERROR_MSG_LOCATION_FAILED);
        }
        return vo;
    }

    private CityInfoVo getCityInfo(AmapRegeoVo amapResponse) {
        if (amapResponse == null || amapResponse.getRegeocode() == null) {
            return null;
        }

        AddressComponent addressComponent = amapResponse.getRegeocode().getAddressComponent();
        if (addressComponent == null || StrUtil.isEmpty(addressComponent.getCity())) {
            return null;
        }

        // 优化查询，只取第一条记录
        LambdaQueryWrapper<Area> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Area::getName, addressComponent.getCity())
                .last("LIMIT " + MAX_QUERY_RESULTS);

        Area area = this.getOne(queryWrapper);
        if (area == null) {
            throw new ServiceException(ERROR_MSG_CITY_NOT_FOUND);
        }

        return new CityInfoVo(area.getName(), area.getCode());
    }
}