package cn.qinys.platform.mobile.service.impl;

import cn.qinys.platform.base.response.Result;
import cn.qinys.platform.base.security.utils.CurrentUtils;
import cn.qinys.platform.entity.wishing.WishingTree;
import cn.qinys.platform.mobile.mapper.UserWishMapper;
import cn.qinys.platform.mobile.mapper.WishingTreeMapper;
import cn.qinys.platform.mobile.req.TreeAddressReq;
import cn.qinys.platform.mobile.req.TreeCreateReq;
import cn.qinys.platform.mobile.req.TreeDetailReq;
import cn.qinys.platform.mobile.req.WishingTreeListReq;
import cn.qinys.platform.mobile.resp.TreeAddressResp;
import cn.qinys.platform.mobile.resp.TreeDetailResp;
import cn.qinys.platform.mobile.resp.TreeListResp;
import cn.qinys.platform.mobile.service.TreeService;
import cn.qinys.platform.mobile.util.CoordUtil;
import cn.qinys.platform.openfeign.UpmsFeignClient;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @author lie tan
 * @description 许愿树服务实现
 * @date 2026-05-24 21:34
 **/
@Slf4j
@Service
public class TreeServiceImpl implements TreeService {

    @Resource
    private WishingTreeMapper treeMapper;
    @Resource
    UserWishMapper wishMapper;
    @Resource
    UpmsFeignClient upmsFeignClient;
    @Resource
    ChatClient chatClient;

    private static final int EARTH_RADIUS = 6371000; // 地球半径（米）

    @Override
    public List<TreeListResp> listNearbyTrees(WishingTreeListReq req) {
        // 查询所有启用的许愿树
        List<TreeListResp> trees = treeMapper.selectActiveTrees();
        // 用户 GPS 是 WGS-84，DB 存的是 GCJ-02，统一转为 GCJ-02 计算距离
        double[] gcj = CoordUtil.wgs84ToGcj02(req.getLng().doubleValue(), req.getLat().doubleValue());
        trees.forEach(tree -> {
            int dist = haversine(gcj[0], gcj[1], tree.getLongitude().doubleValue(), tree.getLatitude().doubleValue());
            tree.setDistance(dist);
            tree.setIsInRange(dist <= (tree.getRadius() != null ? tree.getRadius() : 100));
        });

        List<Integer> integers = this.userTrees();
        // 按距离排序，限制返回数量
        return trees.stream()
                .sorted(Comparator.comparingInt(TreeListResp::getDistance))
                .filter(it -> it.getDistance() <= req.getMaxDistance() || integers.contains(it.getId()))
                .limit(req.getLimit())
                .collect(Collectors.toList());
    }

    @Override
    public TreeDetailResp getTreeDetail(TreeDetailReq req) {
        TreeDetailResp tree = treeMapper.selectDetailById(req.getId());
        // 用户 GPS 是 WGS-84，DB 存的是 GCJ-02，统一转为 GCJ-02 计算距离
        double[] gcj = CoordUtil.wgs84ToGcj02(req.getLng().doubleValue(), req.getLat().doubleValue());
        int dist = haversine(gcj[0], gcj[1], tree.getLongitude().doubleValue(), tree.getLatitude().doubleValue());
        tree.setDistance(dist);
        tree.setIsInRange(dist <= (tree.getRadius() != null ? tree.getRadius() : 100));
        return tree;
    }

    /**
     * Haversine 公式计算两点间距离（米）
     */
    private int haversine(double lng1, double lat1, double lng2, double lat2) {
        double dLat = Math.toRadians(lat2 - lat1);
        double dLng = Math.toRadians(lng2 - lng1);
        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
                + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
                * Math.sin(dLng / 2) * Math.sin(dLng / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        return (int) Math.round(EARTH_RADIUS * c);
    }


    @Override
    public void create(TreeCreateReq req) {
        // 前端传入的是 WGS-84 坐标（天地图 img_w），DB 存储 GCJ-02，需转换
        double[] gcj = CoordUtil.wgs84ToGcj02(req.getLongitude().doubleValue(), req.getLatitude().doubleValue());
        TreeAddressReq addressReq = new TreeAddressReq();
        addressReq.setLatitude(BigDecimal.valueOf(gcj[1]));
        addressReq.setLongitude(BigDecimal.valueOf(gcj[0]));
        String address = upmsFeignClient.getAddressByAltitudeAndLongitude(addressReq).getData();
        String description  = this.getDescription(address);
        WishingTree tree = new WishingTree();
        tree.setName(req.getName());
        tree.setAddress(address);
        tree.setDescription(description);
        tree.setSummary(description);
        tree.setLongitude(BigDecimal.valueOf(gcj[0]));
        tree.setLatitude(BigDecimal.valueOf(gcj[1]));
        tree.setRadius(req.getRadius() != null ? req.getRadius() : 100);
        tree.setCoverImage(req.getCoverImage());
        tree.setIsActive(1);
        treeMapper.insert(tree);
    }

    @Override
    public TreeAddressResp getAddress(TreeAddressReq req) {
        String address = upmsFeignClient.getAddressByAltitudeAndLongitude(req).getData();
        TreeAddressResp addressResp = new TreeAddressResp();
        addressResp.setAddress(address);
        addressResp.setDescription(this.getDescription(address));
        return addressResp;
    }

    private List<Integer> userTrees() {
        Integer userId = Integer.valueOf(CurrentUtils.getCurrentUserId());
        List<Integer> trees = wishMapper.selectUserTrees(userId);
        if (trees == null || trees.isEmpty()) {
            trees = new ArrayList<>();
            trees.add(0);
        }
        return trees;

    }

    private String getDescription(String address) {
        return chatClient.prompt("""
                        你是一个人文地理知识库助手，用户给你一个地址，你根据地址信息给出200 - 300字左右的描述。
                        如果地址是一座城市，给出城市的描述信息如历史，人文景观等；
                        如果是一个小区，简单介绍小区的信息，如开发商，小区建成时间，小区周边等；
                        如果是一个公司，介绍公司的情况，如果是一个旅游景点，也请给出一些描述信息
                        """).user(address)
                .advisors(a -> a.param("chat_memory_conversation_id", UUID.randomUUID().toString()))
                .call().content();
    }

}
