package com.ruoyi.app.flashdelivery.route;

import org.springframework.stereotype.Service;

/** 路线距离服务：优先请求地图路线，异常时使用球面直线距离保证报价仍然可用。 */
@Service
public class FlashDeliveryRouteService {
    private static final double EARTH_RADIUS_METERS = 6_371_000D;
    private final RouteDistanceProvider provider;

    public FlashDeliveryRouteService(RouteDistanceProvider provider) {
        this.provider = provider;
    }

    public RouteDistance calculate(GeoPoint origin, GeoPoint destination) {
        validate(origin);
        validate(destination);
        try {
            RouteDistance route = provider.route(origin.latitude(), origin.longitude(),
                    destination.latitude(), destination.longitude());
            if (route != null && route.distanceMeters() > 0) {
                return route;
            }
        } catch (RuntimeException ignored) {
            // 地图超时、限流或配置缺失不阻断下单，统一进入本地 Haversine 降级。
        }
        // Haversine 只作为降级结果，并通过 source=STRAIGHT_LINE 明确告知调用方。
        double lat1 = Math.toRadians(origin.latitude().doubleValue());
        double lat2 = Math.toRadians(destination.latitude().doubleValue());
        double deltaLat = lat2 - lat1;
        double deltaLon = Math.toRadians(destination.longitude().doubleValue()
                - origin.longitude().doubleValue());
        double a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2)
                + Math.cos(lat1) * Math.cos(lat2)
                * Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2);
        int meters = (int) Math.round(EARTH_RADIUS_METERS * 2D * Math.atan2(Math.sqrt(a), Math.sqrt(1D - a)));
        return new RouteDistance(Math.max(1, meters), null, "STRAIGHT_LINE");
    }

    private void validate(GeoPoint point) {
        if (point == null || point.latitude() == null || point.longitude() == null
                || point.latitude().doubleValue() < -90D || point.latitude().doubleValue() > 90D
                || point.longitude().doubleValue() < -180D || point.longitude().doubleValue() > 180D) {
            throw new IllegalArgumentException("invalid coordinates");
        }
    }
}
