package com.lnkj.ln_jq_app;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.Typeface;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps.AMap;
import com.amap.api.maps.AMapOptions;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.LocationSource;
import com.amap.api.maps.MapView;
import com.amap.api.maps.MapsInitializer;
import com.amap.api.maps.model.BitmapDescriptor;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.MyLocationStyle;
import com.amap.api.maps.model.Poi;
import com.amap.api.navi.AMapNavi;
import com.amap.api.navi.AmapNaviPage;
import com.amap.api.navi.AmapNaviParams;
import com.amap.api.navi.AmapNaviType;
import com.amap.api.navi.AmapPageType;
import com.amap.api.navi.model.AMapCarInfo;
import com.amap.api.navi.model.NaviPoi;
import com.amap.api.services.core.AMapException;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.geocoder.GeocodeResult;
import com.amap.api.services.geocoder.GeocodeSearch;
import com.amap.api.services.geocoder.RegeocodeAddress;
import com.amap.api.services.geocoder.RegeocodeQuery;
import com.amap.api.services.geocoder.RegeocodeResult;
import com.amap.api.services.route.BusRouteResult;
import com.amap.api.services.route.DriveRouteResult;
import com.amap.api.services.route.RideRouteResult;
import com.amap.api.services.route.RouteSearch;
import com.amap.api.services.route.WalkRouteResult;

import org.json.JSONArray;
import org.json.JSONObject;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import androidx.annotation.NonNull;
import io.flutter.plugin.platform.PlatformView;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * 高德地图导航
 */
public class NativeMapView implements PlatformView, LocationSource, AMapLocationListener, GeocodeSearch.OnGeocodeSearchListener, RouteSearch.OnRouteSearchListener, AMap.OnMarkerClickListener {

    private static final String TAG = "NativeMapView";
    private final FrameLayout container;
    private MapView mapView;
    private AMap aMap;
    private OnLocationChangedListener mListener;

    private AMapLocationClient mlocationClient;
    private final Context mContext;
    private Activity mActivity;
    private GeocodeSearch geocoderSearch;
    private RouteSearch routeSearch;
    private final OkHttpClient httpClient = new OkHttpClient();

    // UI组件
    private TextView endInput;
    private LinearLayout searchArea; // 规划路线面板
    private LinearLayout detailPanel; // 详情面板

    private View modeMenu; //模式选择
    private TextView tvStationName, tvStationAddr, planToggleBtn, tvBusinessHours;
    //时间 费用 里程 路费
    private TextView tvDuration, tvDistance, tvTolls, tvTollsFuel, tvPerson, tvPrice, tvPhone;

    private LatLng currentLatLng;
    private String startName = "我的位置";
    private String endName = "";
    private String endAddress = "";
    private LatLng startPoint;
    private LatLng endPoint;
    private boolean isFirstLocation = true;
    private boolean isUserSelectedDestination = false; // 标识用户是否手动选择了目的地
    private final List<Marker> stationMarkers = new ArrayList<>();

    // 存储token和车牌号
    private String token;
    private String plateNumber;

    private String mDebugUrl = "https://beta-esg.api.lnh2e.com/appointment/";
    private String mReleaseUrl = "";

    // 存储货车路线算法接口返回的数据
    private TruckRouteData truckRouteData;
    //当前定位信息
    private AMapLocation mLoc;
    private ImageButton mLocBtn;


    public NativeMapView(Context context, int id, Object args) {
        this.mContext = context;
        mActivity = getActivityFromContext(context);

        // 确保 mActivity 不为 null，如果为 null 则使用 context
        Activity activity = mActivity != null ? mActivity : (context instanceof Activity ? (Activity) context : null);

        MapsInitializer.updatePrivacyShow(activity, true, true);
        MapsInitializer.updatePrivacyAgree(activity, true);

        mapView = new MapView(context);
        mapView.onCreate(null);
        aMap = mapView.getMap();

        container = new FrameLayout(context);
        container.setClickable(true);
        container.setFocusable(true);
        container.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
        container.addView(mapView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

        initLoadingView(context);
        initData(context);
        initServices(context);
        initOverlays(context);
        setupMapUi();

        if (context instanceof MainActivity) {
            ((MainActivity) context).setMapView(this);
        }
    }


    private void initServices(Context context) {
        try {
            geocoderSearch = new GeocodeSearch(context);
            geocoderSearch.setOnGeocodeSearchListener(this);
            routeSearch = new RouteSearch(context);
            routeSearch.setRouteSearchListener(this);
        } catch (AMapException e) {
            Log.e(TAG, "服务初始化失败", e);
        }
    }

    private LinearLayout bottomContainer;

    private void initOverlays(Context context) {
        // --- 底部主容器 (包含两个互斥显示的面板) ---
        bottomContainer = new LinearLayout(context);
        bottomContainer.setOrientation(LinearLayout.VERTICAL);
        bottomContainer.setGravity(Gravity.BOTTOM);
        bottomContainer.setBackgroundResource(R.drawable.rounded_top_bg);
        // 1. 详情面板 (用于显示加氢站详细信息，初始隐藏)
        detailPanel = createDetailPanel(context);
        detailPanel.setVisibility(View.GONE);
        bottomContainer.addView(detailPanel);

        // 2. 搜索规划面板 (初始显示)
        searchArea = new LinearLayout(context);
        searchArea.setOrientation(LinearLayout.VERTICAL);
        searchArea.setBackground(getRoundedDrawable(Color.WHITE, 16));
        int p = dp2px(15);
        searchArea.setPadding(p, p, p, p);
        searchArea.setFocusable(true);
        searchArea.setFocusableInTouchMode(true);

        endInput = new TextView(context);
        endInput.setHint("请输入目的地，不输入则自动匹配推荐加氢站");
        endInput.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_search, 0, 0, 0);
        endInput.setCompoundDrawablePadding(dp2px(8));
        endInput.setTextSize(12);
        endInput.setTextColor(Color.parseColor("#333333"));
        endInput.setHintTextColor(Color.GRAY);
        endInput.setPadding(dp2px(12), dp2px(12), dp2px(12), dp2px(12));
        endInput.setBackground(getRoundedDrawable(Color.parseColor("#F8F8F8"), 8));
        endInput.setSingleLine(true);
        endInput.setGravity(Gravity.CENTER_VERTICAL);
        endInput.setOnClickListener(v -> {
            try {
                Log.d(TAG, "endInput clicked, mActivity=" + (mActivity != null ? "not null" : "null"));

                // 设置回调
                SearchDestinationActivity.setCallback((name, address, lat, lon, district) -> {
                    Log.d(TAG, "Callback received: " + name + ", lat=" + lat + ", lon=" + lon);
                    // 直接设置，不依赖 mActivity.runOnUiThread
                    setDestination(name, address, lat, lon, district);
                });

                // 跳转到搜索目的地页面 - 使用更安全的方式
                Intent intent = new Intent(mContext, SearchDestinationActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                Log.d(TAG, "Starting SearchDestinationActivity with intent");
                mContext.startActivity(intent);

            } catch (Exception e) {
                Log.e(TAG, "Failed to start SearchDestinationActivity", e);
                e.printStackTrace();
                // 显示错误提示
                try {
                    if (mContext != null) {
                        Toast.makeText(mContext, "无法打开搜索页面: " + e.getMessage(), Toast.LENGTH_SHORT).show();
                    }
                } catch (Exception toastException) {
                    Log.e(TAG, "Failed to show toast", toastException);
                }
            }
        });

        searchArea.addView(endInput);

        View vSpace = new View(context);
        searchArea.addView(vSpace, new LinearLayout.LayoutParams(1, dp2px(12)));

        // 创建自定义按钮布局
        LinearLayout planBtnContainer = new LinearLayout(context);
        planBtnContainer.setOrientation(LinearLayout.HORIZONTAL);
        planBtnContainer.setGravity(Gravity.CENTER);
        planBtnContainer.setBackground(getRoundedDrawable(Color.parseColor("#017143"), 99));
        planBtnContainer.setPadding(0, 0, 0, 0);

        // 添加图标
        ImageView pathIcon = new ImageView(context);
        pathIcon.setImageResource(R.drawable.ic_path);
        pathIcon.setColorFilter(Color.WHITE);
        LinearLayout.LayoutParams iconParams = new LinearLayout.LayoutParams(dp2px(20), dp2px(20));
        iconParams.rightMargin = dp2px(6); // 图标和文字之间的间距
        planBtnContainer.addView(pathIcon, iconParams);

        // 添加文字
        TextView planText = new TextView(context);
        planText.setText("规划路线");
        planText.setTextColor(Color.WHITE);
        planText.setTextSize(14);
        planText.setTypeface(Typeface.DEFAULT_BOLD);
        planText.setGravity(Gravity.CENTER);
        planBtnContainer.addView(planText);

        // 设置点击事件
        planBtnContainer.setOnClickListener(v -> calculateRouteBeforeNavi());
        searchArea.addView(planBtnContainer, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dp2px(40)));

        bottomContainer.addView(searchArea);

        // 设置统一的底部间距
        FrameLayout.LayoutParams bottomParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        bottomParams.gravity = Gravity.BOTTOM;
        container.addView(bottomContainer, bottomParams);
        container.setPadding(0, 0, 0, dp2px(65));


        // --- 模式选择菜单 ---
        modeMenu = createModeMenu(context);
        modeMenu.setVisibility(View.GONE);
        // 布局参数：位于规划按钮上方
        FrameLayout.LayoutParams menuParams = new FrameLayout.LayoutParams(dp2px(130), ViewGroup.LayoutParams.WRAP_CONTENT);
        menuParams.gravity = Gravity.BOTTOM | Gravity.END;
        menuParams.setMargins(0, 0, dp2px(15), dp2px(230)); // 高度根据按钮位置调整
        container.addView(modeMenu, menuParams);


        // 加氢规划圆形按钮
        planToggleBtn = new TextView(context);
        planToggleBtn.setText("加氢\n规划");
        planToggleBtn.setTextSize(11);
        planToggleBtn.setTextColor(Color.WHITE);
        planToggleBtn.setGravity(Gravity.CENTER);
        planToggleBtn.setTypeface(Typeface.DEFAULT_BOLD);
        // 设置深绿色圆形背景
        planToggleBtn.setBackground(getCircleDrawable(Color.parseColor("#017143")));
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            planToggleBtn.setElevation(dp2px(6));
        }
        planToggleBtn.setOnClickListener(v -> {
            // 切换菜单显示/隐藏
            modeMenu.setVisibility(modeMenu.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE);
        });

        int layoutSize = dp2px(44);
        FrameLayout.LayoutParams toggleParams = new FrameLayout.LayoutParams(layoutSize, layoutSize);
        toggleParams.gravity = Gravity.BOTTOM | Gravity.END;
        toggleParams.setMargins(0, 0, dp2px(12), dp2px(210)); // 位于定位按钮上方
        container.addView(planToggleBtn, toggleParams);

        // --- 右下角定位按钮 ---
        mLocBtn = new ImageButton(context);
        mLocBtn.setImageResource(R.drawable.ic_location);
        // 设置自定义的白色圆形背景
        mLocBtn.setBackgroundColor(Color.TRANSPARENT);
        // 设置投影（仅在 API 21+ 有效，能产生干净的阴影而非黑块）
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            mLocBtn.setElevation(dp2px(4));
        }
        mLocBtn.setScaleType(ImageView.ScaleType.FIT_CENTER);
        int padding = dp2px(2);
        mLocBtn.setPadding(padding, padding, padding, padding);
        mLocBtn.setOnClickListener(v -> {
            if (currentLatLng != null)
                aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 15f));
        });
        FrameLayout.LayoutParams locParams = new FrameLayout.LayoutParams(layoutSize, layoutSize);
        locParams.setMargins(0, 0, dp2px(15), dp2px(150)); // 调高一点，避开底部的面板
        locParams.gravity = Gravity.BOTTOM | Gravity.END;
        container.addView(mLocBtn, locParams);
    }


    private LinearLayout createDetailPanel(Context context) {
        LinearLayout panel = new LinearLayout(context);
        panel.setOrientation(LinearLayout.VERTICAL);
        int padding = dp2px(15);
        panel.setPadding(padding, padding, padding, padding);

        // --- （包含标题和关闭按钮） ---
        LinearLayout titleLayout = new LinearLayout(context);
        titleLayout.setOrientation(LinearLayout.HORIZONTAL);
        titleLayout.setGravity(Gravity.CENTER_VERTICAL);

        // 站点名称 (设置 weight: 1 占据剩余空间)
        tvStationName = new TextView(context);
        tvStationName.setTextSize(18);
        tvStationName.setTextColor(Color.BLACK);
        tvStationName.setTypeface(Typeface.DEFAULT_BOLD);
        LinearLayout.LayoutParams nameParams = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1.0f);
        titleLayout.addView(tvStationName, nameParams);

        // 关闭按钮 (X)
        ImageView ivClose = new ImageView(context);
        ivClose.setImageResource(R.drawable.ic_close);
        ivClose.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
        ivClose.setPadding(dp2px(5), dp2px(5), dp2px(5), dp2px(5));
        ivClose.setOnClickListener(v -> {
            resetView();
        });

        LinearLayout.LayoutParams closeParams = new LinearLayout.LayoutParams(dp2px(28), dp2px(28));
        titleLayout.addView(ivClose, closeParams);

        panel.addView(titleLayout);

        //营业时间和地址
        tvBusinessHours = new TextView(context);
        tvBusinessHours.setTextSize(13);
        tvBusinessHours.setPadding(0, dp2px(4), 0, 0);
        tvBusinessHours.setTextColor(Color.GRAY);
        panel.addView(tvBusinessHours);

        tvStationAddr = new TextView(context);
        tvStationAddr.setTextSize(13);
        tvStationAddr.setPadding(0, dp2px(4), 0, 0);
        tvStationAddr.setTextColor(Color.GRAY);
        panel.addView(tvStationAddr);

        /*内容*/
        LinearLayout routeInfoLayout = new LinearLayout(context);
        routeInfoLayout.setOrientation(LinearLayout.VERTICAL);
        routeInfoLayout.setPadding(0, dp2px(5), 0, 0);

        // 第一行：预计时间
        LinearLayout row1 = new LinearLayout(context);
        row1.setOrientation(LinearLayout.HORIZONTAL);
        row1.setGravity(Gravity.CENTER_VERTICAL);
        row1.setPadding(0, dp2px(8), 0, 0); // 增加行间距
        tvDuration = createInfoItem(row1, R.drawable.ic_time, "预计时间：", "-", 1.0f);
        tvTollsFuel = createInfoItem(row1, R.drawable.ic_fuel, "加氢费用：", "-", 1.0f);
        routeInfoLayout.addView(row1);

        // 第二行：里程 + 过路费
        LinearLayout row2 = new LinearLayout(context);
        row2.setOrientation(LinearLayout.HORIZONTAL);
        row2.setGravity(Gravity.CENTER_VERTICAL);
        row2.setPadding(0, dp2px(10), 0, 0); // 增加行间距

        // 里程
        tvDistance = createInfoItem(row2, R.drawable.ic_mileage, "行驶里程：", "-", 1.0f);
        // 过路费
        tvTolls = createInfoItem(row2, R.drawable.ic_toll, "过路费：", "-", 1.0f);
        routeInfoLayout.addView(row2);

        //第三行
        LinearLayout row3 = new LinearLayout(context);
        row3.setOrientation(LinearLayout.HORIZONTAL);
        row3.setGravity(Gravity.CENTER_VERTICAL);
        row3.setPadding(0, dp2px(8), 0, 0); // 增加行间距
        tvPerson = createInfoItem(row3, R.drawable.ic_person, "站联系人：", "-", 1.0f);
        tvPrice = createInfoItem(row3, R.drawable.ic_price, "加氢价格：", "-", 1.0f);
        routeInfoLayout.addView(row3);

        LinearLayout row4 = new LinearLayout(context);
        row4.setOrientation(LinearLayout.HORIZONTAL);
        row4.setGravity(Gravity.CENTER_VERTICAL);
        row4.setPadding(0, dp2px(8), 0, 0); // 增加行间距
        tvPhone = createInfoItem(row4, R.drawable.ic_phone, "联系方式：", "-", 1.0f);
        routeInfoLayout.addView(row4);


        panel.addView(routeInfoLayout);

        Button startNaviBtn = new Button(context);
        startNaviBtn.setText("开始导航");
        startNaviBtn.setTextColor(Color.WHITE);
        startNaviBtn.setBackground(getRoundedDrawable(Color.parseColor("#017143"), 99));
        startNaviBtn.setOnClickListener(v -> startRouteSearch());

        LinearLayout.LayoutParams btnParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dp2px(48));
        btnParams.topMargin = dp2px(15);
        panel.addView(startNaviBtn, btnParams);

        return panel;
    }

    private void resetView() {
        if (detailPanel != null)
            detailPanel.setVisibility(View.GONE);
        searchArea.setVisibility(View.VISIBLE);
        planToggleBtn.setVisibility(View.VISIBLE);
        mLocBtn.setVisibility(View.VISIBLE);

    }

    private boolean isGetInputtips = false;

    private void calculateRouteBeforeNavi() {
        if (startPoint == null) {
            Toast.makeText(mContext, "正在定位...", Toast.LENGTH_SHORT).show();
            return;
        }

        if (endPoint == null) {
            Toast.makeText(mContext, "请先选择目的地", Toast.LENGTH_SHORT).show();
            return;
        }

        //如果是输入地址提示内容

        if (isGetInputtips) {
            truckRouteData = null;

            RouteSearch.FromAndTo fromAndTo = new RouteSearch.FromAndTo(new LatLonPoint(startPoint.latitude, startPoint.longitude), new LatLonPoint(endPoint.latitude, endPoint.longitude));
            RouteSearch.DriveRouteQuery query = new RouteSearch.DriveRouteQuery(fromAndTo, RouteSearch.DRIVING_SINGLE_DEFAULT, null, null, "");
            routeSearch.calculateDriveRouteAsyn(query);


            // 开始规划前隐藏输入框面板
            searchArea.setVisibility(View.GONE);
        } else {
            fetchTruckRouteAlgorithm(mLoc);
        }
    }

    @Override
    public void onDriveRouteSearched(DriveRouteResult result, int rCode) {
        if (mActivity == null) {
            Log.e(TAG, "mActivity is null in onDriveRouteSearched");
            return;
        }

        mActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {

                String hydrogenCost = "-"; // 默认显示横线
                String hydrogenPrice = "-"; // 默认显示横线
                String liaisonName = "-";
                String liaisonPhone = "-";
                String startBusiness = "-";
                String endBusiness = "-";
                double distanceKm = 0;
                String distanceKmStr = "-";
                long durationMin = 0;
                String durationMinStr = "-";
                String tolls = "-";

                if (rCode == AMapException.CODE_AMAP_SUCCESS && result != null && !result.getPaths().isEmpty()) {

                    // 规划成功，显示详情面板，隐藏模式选择
                    if (detailPanel != null)
                        detailPanel.setVisibility(View.VISIBLE);
                    if (planToggleBtn != null)
                        planToggleBtn.setVisibility(View.GONE);
                    if (mLocBtn != null)
                        mLocBtn.setVisibility(View.GONE);
                    if (modeMenu != null)
                        modeMenu.setVisibility(View.GONE);

                    tvStationName.setText(endName);
                    tvStationAddr.setText(endAddress);


                    if (truckRouteData != null) {
                        PathDto pathDto = truckRouteData.pathDto;
                        if (pathDto != null) {
                            distanceKm = pathDto.distance / 1000f;
                            durationMin = pathDto.duration / 60;
                            tolls = pathDto.tolls + "元";

                            distanceKmStr = String.format("%.1f", distanceKm) + "公里";
                            durationMinStr = durationMin + "分钟";
                        }
                    }


                    // 增加多级非空校验，防止点击搜索条目时崩溃
                    if (truckRouteData != null &&
                            truckRouteData.algorithmPath != null &&
                            truckRouteData.algorithmPath.hydrogenCost != null &&
                            !truckRouteData.algorithmPath.hydrogenCost.isEmpty()) {
                        hydrogenCost = truckRouteData.algorithmPath.hydrogenCost;
                        hydrogenCost = (isGetInputtips ? "--" : hydrogenCost) + "元";
                    }

                    tvDuration.setText("预计时间：" + durationMinStr);
                    tvDistance.setText("行驶里程：" + distanceKmStr);
                    tvTolls.setText("过路费：" + tolls);
                    tvTollsFuel.setText("预计加氢费用：" + hydrogenCost);


                    if (truckRouteData != null) {
                        DestinationSite destinationSite = truckRouteData.destinationSite;
                        if (destinationSite != null) {
                            startBusiness = destinationSite.startBusiness;
                            endBusiness = destinationSite.endBusiness;
                            hydrogenPrice = destinationSite.hydrogenPrice + "/L";
                            liaisonName = destinationSite.liaisonName;
                            liaisonPhone = destinationSite.liaisonPhone;
                            //开始结束时间
                            startBusiness = startBusiness + "-" + endBusiness;
                        }
                    }

                    tvBusinessHours.setText("营业时间：" + startBusiness);
                    if (liaisonName != null && liaisonName.length() > 5) {
                        liaisonName = liaisonName.substring(0, 5) + "...";
                    }
                    tvPerson.setText("站联系人：" + liaisonName);
                    tvPrice.setText("加氢价格：" + hydrogenPrice);
                    tvPhone.setText("联系方式：" + liaisonPhone);



                    aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(endPoint, 13f));


                } else {
                    // 规划失败回退面板
                    searchArea.setVisibility(View.VISIBLE);
                    Toast.makeText(mContext, "路径规划失败: " + rCode, Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    private void startRouteSearch() {
        if (mActivity == null || startPoint == null) {
            Toast.makeText(mContext, "定位信息不足，请稍后再试", Toast.LENGTH_SHORT).show();
            return;
        }

        //确定目的地坐标和名称
        LatLng finalDestinationLatLng = null;
        String finalDestinationName = endName;

        // 优先级：用户手动选择 > truckRouteData (接口返回的精准点) > endPoint (地图点击/搜索的点)
        if (isUserSelectedDestination && endPoint != null) {
            finalDestinationLatLng = endPoint;
            finalDestinationName = endName;
        } else if (truckRouteData != null && truckRouteData.destinationSite != null) {
            // 否则使用接口返回的推荐加氢站地址
            String latStr = truckRouteData.destinationSite.latitude;
            String lngStr = truckRouteData.destinationSite.longitude;

            //防止 parseDouble 崩溃
            if (latStr != null && !latStr.isEmpty() && lngStr != null && !lngStr.isEmpty()) {
                try {
                    finalDestinationLatLng = new LatLng(Double.parseDouble(latStr),
                            Double.parseDouble(lngStr));
                    if (truckRouteData.destinationSite.name != null &&
                            !truckRouteData.destinationSite.name.isEmpty()) {
                        finalDestinationName = truckRouteData.destinationSite.name;
                    }
                } catch (NumberFormatException e) {
                    Log.e(TAG, "解析 truckRouteData 坐标失败: " + e.getMessage());
                }
            }
        }

        // 如果接口数据不可用，使用之前标记点/输入点作为兜底
        if (finalDestinationLatLng == null) {
            finalDestinationLatLng = endPoint;
        }

        // 最终校验
        if (finalDestinationLatLng == null) {
            Toast.makeText(mContext, "请先选择有效的目的地", Toast.LENGTH_SHORT).show();
            return;
        }

        //获取途径点
        List<NaviPoi> waysPoiIds = new ArrayList<>();
        if (truckRouteData != null && truckRouteData.pathDto != null && truckRouteData.pathDto.naviList !=
                null) {
            for (NaviPoint np : truckRouteData.pathDto.naviList) {
                if (np.coordinate != null && !TextUtils.isEmpty(np.coordinate.latitude) &&
                        !TextUtils.isEmpty(np.coordinate.longitude)) {
                    try {
                        double lat = Double.parseDouble(np.coordinate.latitude);
                        double lng = Double.parseDouble(np.coordinate.longitude);
                        waysPoiIds.add(new NaviPoi(np.name, new LatLng(lat, lng), np.poiId));
                    } catch (Exception e) {
                        Log.e(TAG, "途径点坐标解析错误: " + np.name);
                    }
                }
            }
        }
        //车辆信息
        AMapCarInfo carInfo = new AMapCarInfo();
        carInfo.setCarNumber(plateNumber);

        if (truckRouteData != null) {
            carInfo.setCarType(String.valueOf(truckRouteData.truckDto.mcarType));
            carInfo.setVehicleAxis(String.valueOf(truckRouteData.truckDto.mvehicleAxis));
            carInfo.setVehicleHeight(truckRouteData.truckDto.mvehicleHeight);
            carInfo.setVehicleLength(truckRouteData.truckDto.mvehicleLength);
            carInfo.setVehicleWidth(truckRouteData.truckDto.mvehicleWidth);
            carInfo.setVehicleSize(String.valueOf(truckRouteData.truckDto.mvehicleSize));
            carInfo.setVehicleLoad(truckRouteData.truckDto.mvehicleLoad);
            carInfo.setVehicleWeight(truckRouteData.truckDto.mvehicleWeight);
            carInfo.setRestriction(truckRouteData.truckDto.isRestriction);
            carInfo.setVehicleLoadSwitch(truckRouteData.truckDto.mvehicleLoadSwitch);
        }


        // 检查途径点数量，决定使用哪种导航方式
        int wayPointsCount = waysPoiIds.size();
        Log.d(TAG, "途经点数量: " + wayPointsCount);

        //如果是输入地址提示内容，不判断途经点
        if (isGetInputtips) {
            wayPointsCount = 0;
        }
        if (wayPointsCount > 3) {
            // 途经点超过3个，跳转到 NavigationActivity
            Intent intent = new Intent(mContext, NavigationActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

            // 设置起点和终点 POI
            NaviPoi startNaviPoi = new NaviPoi("", startPoint, "");
            NaviPoi endNaviPoi = new NaviPoi("", finalDestinationLatLng, "");
            intent.putExtra("startPoi", startNaviPoi);
            intent.putExtra("endPoi", endNaviPoi);

            // 设置车辆信息
            if (truckRouteData != null && truckRouteData.truckDto != null) {
                intent.putExtra("carInfo", carInfo);
            }

            // 设置途径点
            if (!waysPoiIds.isEmpty()) {// 必须转换为 ArrayList 才能调用 putParcelableArrayListExtra
                ArrayList<NaviPoi> wayPointsArrayList = new ArrayList<>(waysPoiIds);
                intent.putParcelableArrayListExtra("wayPoints", wayPointsArrayList);
            }

            mContext.startActivity(intent);

        } else {
            Poi start = new Poi(startName, startPoint, "");
            Poi end = new Poi(finalDestinationName, finalDestinationLatLng, "");
            AmapNaviParams params = new AmapNaviParams(start, null, end, AmapNaviType.DRIVER,
                    AmapPageType.ROUTE);

            try {
                AMapNavi mAMapNavi = AMapNavi.getInstance(mContext);
                // 设置车辆信息
                if (truckRouteData != null && truckRouteData.truckDto != null) {
                    params.setCarInfo(carInfo);
                    mAMapNavi.setCarInfo(carInfo);
                }
                params.setNeedDestroyDriveManagerInstanceWhenNaviExit(true);
                AmapNaviPage.getInstance().showRouteActivity(mActivity, params, null);
            } catch (Exception e) {
                Log.e(TAG, "配置导航参数出错: " + e.getMessage());
            }
        }
    }

    private void initData(Context context) {
        //获取从Flutter端存储的车牌和token
        android.content.SharedPreferences prefs = context.getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE);
        String plateNumber = prefs.getString("flutter.plateNumber", "");
        String token = prefs.getString("flutter.token", "");

        Log.d(TAG, "initData - plateNumber: " + plateNumber + ", token: " + (token.isEmpty() ? "empty" : "present"));

        // 保存token供后续使用
        this.token = token;
        this.plateNumber = plateNumber;
    }

    // 当前选中的站点ID，默认id和选择地图id
    private String selectedSiteId = "";

    /**
     * 定位成功后调用，地图选点后调用
     * 获取货车路线算法信息
     */
    private void fetchTruckRouteAlgorithm(AMapLocation loc) {
        if (plateNumber == null || plateNumber.isEmpty()) {
            Toast.makeText(mActivity,"请先绑定车辆后进行导航",Toast.LENGTH_SHORT).show();
            return;
        }
        showLoading();
        try {
            JSONObject json = new JSONObject();
            json.put("longitude", String.valueOf(loc.getLongitude()));
            json.put("latitude", String.valueOf(loc.getLatitude()));
            json.put("plateNumber", plateNumber);
            json.put("hydrogenSiteId", selectedSiteId);

            Request.Builder requestBuilder = new Request.Builder().url(mDebugUrl + "truck/truckRouteAlgorithm").post(RequestBody.create(json.toString(), MediaType.parse("application/json")));

            if (token != null && !token.isEmpty()) {
                requestBuilder.addHeader("asoco-token", token);
            }
            Log.d("566-", "asoco-token:" + token + "requestBuilder:" + json);
            httpClient.newCall(requestBuilder.build()).enqueue(new Callback() {
                @Override
                public void onFailure(@NonNull Call call, @NonNull IOException e) {
                    Log.e(TAG, "fetchTruckRouteAlgorithm failed", e);
                    dismissLoading();
                }

                @Override
                public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                    if (response.isSuccessful() && response.body() != null) {
                        try {
                            String responseString = response.body().string();
                            Log.d(TAG, "fetchTruckRouteAlgorithm response: " + responseString);

                            JSONObject res = new JSONObject(responseString);
                            if (res.getInt("code") == 200) {
                                JSONObject data = res.getJSONObject("data");
                                truckRouteData = parseTruckRouteData(data);
                                Log.d(TAG, "TruckRouteAlgorithm data loaded");

                                dismissLoading();

                                mActivity.runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        // 开始规划前隐藏输入框面板
                                        searchArea.setVisibility(View.GONE);

                                        RouteSearch.FromAndTo fromAndTo = new RouteSearch.FromAndTo(new LatLonPoint(startPoint.latitude, startPoint.longitude), new LatLonPoint(endPoint.latitude, endPoint.longitude));
                                        RouteSearch.DriveRouteQuery query = new RouteSearch.DriveRouteQuery(fromAndTo, RouteSearch.DRIVING_SINGLE_DEFAULT, null, null, "");
                                        routeSearch.calculateDriveRouteAsyn(query);
                                    }
                                });
                            } else {
                                dismissLoading();
                            }
                        } catch (Exception e) {
                            Log.e(TAG, "parseTruckRouteAlgorithm error", e);
                        }
                    } else {
                        dismissLoading();
                    }
                }
            });
        } catch (Exception e) {
            Log.e(TAG, "fetchTruckRouteAlgorithm error", e);
            dismissLoading();
        }
    }

    private ProgressBar progressBar;
    private FrameLayout loadingOverlay;

    private void initLoadingView(Context context) {
        // 创建遮罩层 (全屏透明，拦截点击)
        loadingOverlay = new FrameLayout(context);
        loadingOverlay.setLayoutParams(new FrameLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT));
        loadingOverlay.setClickable(true); // 拦截点击
        loadingOverlay.setFocusable(true);
        loadingOverlay.setVisibility(View.GONE); // 默认隐藏

        progressBar = new ProgressBar(context, null, android.R.attr.progressBarStyleLarge);
        FrameLayout.LayoutParams progressParams = new FrameLayout.LayoutParams(
                dp2px(45), dp2px(45));
        progressParams.gravity = Gravity.CENTER; // 居中显示

        // 把进度条加到遮罩层
        loadingOverlay.addView(progressBar, progressParams);

        // 最后把整个遮罩层添加到主容器的最顶层
        container.addView(loadingOverlay);
    }

    private void showLoading() {
        if (mActivity == null)
            return;
        mActivity.runOnUiThread(() -> {
            if (loadingOverlay != null) {
                loadingOverlay.setVisibility(View.VISIBLE);
            }
            // 如果想在加载时给用户文字提示，可以动态加一个 TextView 在 ProgressBar 下方
        });
    }

    private void dismissLoading() {
        if (mActivity == null)
            return;
        mActivity.runOnUiThread(() -> {
            if (loadingOverlay != null) {
                loadingOverlay.setVisibility(View.GONE);
            }
        });
    }

    private void setupMapUi() {
        aMap.setLocationSource(this);
        aMap.setMyLocationEnabled(true);
        aMap.setOnMarkerClickListener(this);

        // 添加地图点击监听，当 detailPanel 显示时点击地图就执行 resetView
        aMap.setOnMapClickListener(latLng -> {
            if (detailPanel != null && detailPanel.getVisibility() == View.VISIBLE) {
                resetView();
            }
            modeMenu.setVisibility(View.GONE);
        });
        aMap.setOnPOIClickListener(poi -> {
            if (detailPanel != null && detailPanel.getVisibility() == View.VISIBLE) {
                resetView();
            }
            modeMenu.setVisibility(View.GONE);
        });

        MyLocationStyle myLocationStyle = new MyLocationStyle();
        try {
            Bitmap carBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.car);
            if (carBitmap != null) {
                Bitmap scaledBitmap = Bitmap.createScaledBitmap(carBitmap, dp2px(30), dp2px(30), true);
                myLocationStyle.myLocationIcon(BitmapDescriptorFactory.fromBitmap(scaledBitmap));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        myLocationStyle.anchor(0.5f, 0.5f);
        myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_SHOW);
        aMap.setMyLocationStyle(myLocationStyle);
        aMap.getUiSettings().setZoomControlsEnabled(false);
        aMap.getUiSettings().setLogoPosition(AMapOptions.LOGO_POSITION_BOTTOM_LEFT);
    }

    private GradientDrawable getRoundedDrawable(int color, int radiusDp) {
        GradientDrawable shape = new GradientDrawable();
        shape.setShape(GradientDrawable.RECTANGLE);
        shape.setCornerRadius(dp2px(radiusDp));
        shape.setColor(color);
        return shape;
    }

    private int dp2px(float dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, mContext.getResources().getDisplayMetrics());
    }

    @Override
    public void activate(OnLocationChangedListener listener) {
        mListener = listener;
        startLocation();
    }

    @Override
    public void deactivate() {
        mListener = null;
        if (mlocationClient != null)
            mlocationClient.stopLocation();
    }

    public void setDestination(String name, String address, double lat, double lon, String district) {
        endName = name;
        endAddress = address;
        endPoint = new LatLng(lat, lon);
        isUserSelectedDestination = true;
        isGetInputtips = true;

        Log.d(TAG, "setDestination called with name=" + name);

        // 简化逻辑，直接设置文本
        endInput.post(() -> {
            try {
                endInput.setText(district != null && !district.isEmpty() ? (name + " " + district ): name);
            } catch (Exception e) {
                Log.e(TAG, "Failed to set text to endInput", e);
            }
        });
    }


    /**
     * 设置 Activity 实例
     */
    public void setActivity(Activity activity) {
        this.mActivity = activity;
    }

    public void startLocation() {
        if (mlocationClient == null) {
            try {
                mlocationClient = new AMapLocationClient(mContext);
                AMapLocationClientOption option = new AMapLocationClientOption();
                mlocationClient.setLocationListener(this);
                option.setNeedAddress(true);
                option.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
                mlocationClient.setLocationOption(option);
                mlocationClient.startLocation();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onLocationChanged(AMapLocation loc) {
        mLoc = loc;
        if (mLoc != null && mLoc.getErrorCode() == 0) {
            currentLatLng = new LatLng(mLoc.getLatitude(), mLoc.getLongitude());
            if (mListener != null)
                mListener.onLocationChanged(mLoc);
            if (isFirstLocation) {
                isFirstLocation = false;
                startPoint = currentLatLng;
                aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 14f));
                getAddressByLatlng(currentLatLng);
                fetchRecommendStation(mLoc);
                fetchNearbyStations(mLoc);

            }
        }
    }

    private void getAddressByLatlng(LatLng latLng) {
        geocoderSearch.getFromLocationAsyn(new RegeocodeQuery(new LatLonPoint(latLng.latitude, latLng.longitude), 200, GeocodeSearch.AMAP));
    }

    @Override
    public void onRegeocodeSearched(RegeocodeResult result, int rCode) {
        if (rCode == 1000 && result != null) {
            RegeocodeAddress addr = result.getRegeocodeAddress();
            startName = addr.getStreetNumber() != null ? addr.getStreetNumber().getStreet() : addr.getDistrict();
        }
    }

    /**
     * 获取定位地区的推荐站点
     *
     * @param loc
     */
    private void fetchRecommendStation(AMapLocation loc) {
        try {
            JSONObject json = new JSONObject();
            json.put("province", loc.getProvince());
            json.put("city", loc.getCity().isEmpty() ? loc.getProvince() : loc.getCity());
            json.put("longitude", loc.getLongitude());
            json.put("latitude", loc.getLatitude());

            httpClient.newCall(new Request.Builder().url(mDebugUrl + "station/getStationInfoByArea").post(RequestBody.create(json.toString(), MediaType.parse("application/json"))).build()).enqueue(new Callback() {
                @Override
                public void onFailure(@NonNull Call call, @NonNull IOException e) {
                }

                @Override
                public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                    if (response.isSuccessful() && response.body() != null) {
                        try {
                            JSONObject res = new JSONObject(response.body().string());
                            if (res.getInt("code") == 0 && !res.isNull("data")) {
                                JSONObject data = res.getJSONObject("data");
                                endPoint = new LatLng(data.getDouble("latitude"), data.getDouble("longitude"));
                                endName = data.getString("name");
                                selectedSiteId = data.optString("id", "");
                                endAddress = data.optString("address", "");
                                isUserSelectedDestination = false; // 系统推荐的地址，不是用户选择
                                new Handler(Looper.getMainLooper()).post(() -> {
                                    markStation(endPoint, endName, endAddress, selectedSiteId, true);
                                });
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void fetchNearbyStations(AMapLocation loc) {
        try {
            JSONObject json = new JSONObject();
            json.put("longitude", loc.getLongitude());
            json.put("latitude", loc.getLatitude());

            httpClient.newCall(new Request.Builder().url(mDebugUrl + "station/getNearbyHydrogenStationsByLocation").post(RequestBody.create(json.toString(), MediaType.parse("application/json"))).build()).enqueue(new Callback() {
                @Override
                public void onFailure(@NonNull Call call, @NonNull IOException e) {
                }

                @Override
                public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                    if (response.isSuccessful() && response.body() != null) {
                        try {
                            JSONObject res = new JSONObject(response.body().string());
                            JSONArray array = res.getJSONArray("data");
                            new Handler(Looper.getMainLooper()).post(() -> {
                                for (int i = 0; i < array.length(); i++) {
                                    try {
                                        JSONObject item = array.getJSONObject(i);
                                        String id = item.getString("id");
                                        //推荐站点跳出
                                        if (selectedSiteId.equals(id)) {
                                            continue;
                                        }
                                        markStation(new LatLng(item.getDouble("latitude"), item.getDouble("longitude")), item.getString("name"), item.getString("address"), id, false);
                                    } catch (Exception ignored) {
                                    }
                                }
                            });
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private void markStation(LatLng latLng, String name, String address, String stationId, boolean isRecommend) {

        String displayName = name;
        if (displayName != null && displayName.length() > 7) {
            displayName = displayName.substring(0, 7) + "...";
        }

        BitmapDescriptor icon = getMarkerIconWithText(mContext, displayName, isRecommend);

        MarkerOptions markerOptions = new MarkerOptions()
                .title(name).
                position(latLng).icon(icon).anchor(0.5f, 0.8f);

        Marker m = aMap.addMarker(markerOptions);

        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("latLng", latLng);
        dataMap.put("stationId", stationId);
        dataMap.put("address", address);
        dataMap.put("name", name);
        m.setObject(dataMap);

        stationMarkers.add(m);
    }

    @Override
    public boolean onMarkerClick(Marker marker) {

        //地图选点
        for (Marker m : stationMarkers) {
            Object obj = m.getObject();
            if (obj instanceof Map) {
                Map<String, Object> dataMap = (Map<String, Object>) obj;
                String name = (String) dataMap.get("name");

                if (name != null) {
                    // 截取显示名称（最多7个字符）
                    String displayName = name.length() > 7 ? name.substring(0, 7) + "..." :
                            name;
                    boolean isSelected = m.equals(marker);

                    // 使用 getMarkerIconWithText 创建带文字的图标
                    BitmapDescriptor icon = getMarkerIconWithText(mContext, displayName,
                            isSelected);
                    m.setIcon(icon);
                } else {
                    // 如果没有 name，降级到直接设置图标
                    m.setIcon(BitmapDescriptorFactory.fromResource(m.equals(marker) ?
                            R.drawable.ic_marker : R.drawable.ic_un_marker));
                }
            }
        }


        Object obj = marker.getObject();
        if (obj instanceof Map) {
            Map<String, Object> dataMap = (Map<String, Object>) obj;

            //  获取坐标并赋值
            LatLng latLng = (LatLng) dataMap.get("latLng");
            if (latLng != null) {
                this.endPoint = latLng;
            }

            //  获取站点ID并赋值
            String stationId = (String) dataMap.get("stationId");
            String address = (String) dataMap.get("address");
            if (stationId != null) {
                this.selectedSiteId = stationId;
                this.endAddress = address;
            }

            //  更新 UI 和 业务逻辑
            endName = marker.getTitle();
            isUserSelectedDestination = true; // 标识用户手动选择了目的地
            isGetInputtips = false;

            endInput.setText("");

            // 需要传入当前位置以便接口计算路线
            if (mlocationClient != null && mlocationClient.getLastKnownLocation() != null) {
                fetchTruckRouteAlgorithm(mlocationClient.getLastKnownLocation());
            } else if (currentLatLng != null) {
                // 如果没有精准定位，尝试使用上次记录的经纬度
                AMapLocation tempLoc = new AMapLocation("");
                tempLoc.setLatitude(currentLatLng.latitude);
                tempLoc.setLongitude(currentLatLng.longitude);
                fetchTruckRouteAlgorithm(tempLoc);
            }


            //  计算路径
            calculateRouteBeforeNavi();
        }

        return true;
    }

    @Override
    public void onGeocodeSearched(GeocodeResult r, int c) {
    }

    @Override
    public void onBusRouteSearched(BusRouteResult r, int c) {
    }

    @Override
    public void onWalkRouteSearched(WalkRouteResult r, int c) {
    }

    @Override
    public void onRideRouteSearched(RideRouteResult r, int c) {
    }

    private Activity getActivityFromContext(Context context) {
        if (context instanceof Activity)
            return (Activity) context;
        if (context instanceof android.content.ContextWrapper)
            return getActivityFromContext(((android.content.ContextWrapper) context).getBaseContext());
        return null;
    }

    public void onResume() {
        mapView.onResume();
    }

    public void onPause() {
        mapView.onPause();
    }

    public void onSaveInstanceState(Bundle out) {
        mapView.onSaveInstanceState(out);
    }

    @Override
    public View getView() {
        return container;
    }

    @Override
    public void dispose() {
        if (mlocationClient != null) {
            mlocationClient.stopLocation();
            mlocationClient.onDestroy();
        }
        mapView.onDestroy();
    }

    public BitmapDescriptor getMarkerIconWithText(Context context, String text, boolean isRecommend) {
        // 创建主容器
        LinearLayout container = new LinearLayout(context);
        container.setOrientation(LinearLayout.VERTICAL);
        container.setGravity(Gravity.CENTER_HORIZONTAL);
        // 必须要给容器本身也设置一个基础参数，否则测量可能失败
        container.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));

        // 文字部分：必须显式设置 LayoutParams
        TextView textView = new TextView(context);
        textView.setText(text);
        textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12);
        textView.setTextColor(Color.BLACK);
        textView.setTypeface(null, Typeface.BOLD);
        // 设置文字的参数为 WRAP_CONTENT
        LinearLayout.LayoutParams textLp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        textView.setLayoutParams(textLp);
        container.addView(textView);

        // 图标部分：设置固定大小
        ImageView imageView = new ImageView(context);
        imageView.setImageResource(isRecommend ? R.drawable.ic_marker : R.drawable.ic_un_marker);

        int size = dp2px(30);
        LinearLayout.LayoutParams imgLp = new LinearLayout.LayoutParams(size, size);
        imgLp.topMargin = dp2px(2);
        imageView.setLayoutParams(imgLp);
        imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
        container.addView(imageView);

        // --- 精准测量 ---
        int spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        container.measure(spec, spec);

        // 获取测量后的实际宽高
        int measuredWidth = container.getMeasuredWidth();
        int measuredHeight = container.getMeasuredHeight();

        // 如果测出来是 0，说明有问题
        if (measuredWidth <= 0 || measuredHeight <= 0) {
            // 兜底逻辑：如果测量失败，给一个默认大小
            measuredWidth = dp2px(100);
            measuredHeight = dp2px(60);
        }

        container.layout(0, 0, measuredWidth, measuredHeight);

        //  绘制到 Bitmap
        Bitmap bitmap = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        // 绘制前可以选清空背景（透明）
        canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
        container.draw(canvas);

        return BitmapDescriptorFactory.fromBitmap(bitmap);
    }

    /**
     * 辅助方法：创建带图标的文本项
     */
    private TextView createInfoItem(LinearLayout parent, int iconRes, String label, String value, float weight) {
        LinearLayout itemContainer = new LinearLayout(mContext);
        itemContainer.setOrientation(LinearLayout.HORIZONTAL);
        itemContainer.setGravity(Gravity.CENTER_VERTICAL);

        // 图标
        ImageView iv = new ImageView(mContext);
        iv.setImageResource(iconRes);
        iv.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
        iv.setColorFilter(Color.parseColor("#017143")); // 统一设为主题绿
        itemContainer.addView(iv, new LinearLayout.LayoutParams(dp2px(18), dp2px(18)));

        // 文本内容
        TextView tv = new TextView(mContext);


        tv.setText(label + value);

        tv.setTextSize(12);
        tv.setTextColor(Color.parseColor("#ff1d2129"));
        tv.setPadding(dp2px(6), 0, 0, 0);

        LinearLayout.LayoutParams tvParams = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1.0f);
        itemContainer.addView(tv, tvParams);

        // 将整个项加入父容器
        LinearLayout.LayoutParams containerParams = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, weight);
        parent.addView(itemContainer, containerParams);

        return tv; // 返回TextView以便后续更新内容
    }


    // 创建模式菜单视图
    private View createModeMenu(Context context) {
        LinearLayout menu = new LinearLayout(context);
        menu.setOrientation(LinearLayout.VERTICAL);
        menu.setBackground(getRoundedDrawable(Color.WHITE, 12));
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            menu.setElevation(dp2px(10));
        }

        // 1. 成本计算模式 (高亮绿色头部)
        TextView item1 = createMenuItem(context, "成本计算模式", false);
        item1.setOnClickListener(v -> switchMode("成本计算"));

        // 2. 送货规划模式
        TextView item2 = createMenuItem(context, "送货规划模式", false);
        item2.setOnClickListener(v -> switchMode("送货规划"));

        // 3. 加氢规划模式
        TextView item3 = createMenuItem(context, "加氢规划模式", true);
        item3.setOnClickListener(v -> switchMode("加氢规划"));

        menu.addView(item3);
        menu.addView(item2);
        menu.addView(item1);
        return menu;
    }

    private TextView createMenuItem(Context context, String text, boolean isHighlight) {
        TextView tv = new TextView(context);
        tv.setText(text);
        tv.setTextSize(13);
        tv.setPadding(dp2px(15), dp2px(12), dp2px(15), dp2px(12));
        tv.setGravity(Gravity.CENTER);
        if (isHighlight) {
            // 顶部圆角绿色背景
            tv.setBackground(getTopRoundedDrawable(Color.parseColor("#27AE60"), 12));
        } else {
            tv.setBackgroundColor(Color.TRANSPARENT);
        }
        tv.setTextColor(Color.parseColor(isHighlight ? "#ffffffff" : "#ffc9cdd4"));
        return tv;
    }

    private void switchMode(String mode) {
        // 处理模式切换逻辑
        modeMenu.setVisibility(View.GONE);
    }

    // 获取纯圆形背景
    private GradientDrawable getCircleDrawable(int color) {
        GradientDrawable gd = new GradientDrawable();
        gd.setColor(color);
        gd.setShape(GradientDrawable.OVAL);
        return gd;
    }

    // 获取顶部带圆角，底部直角的背景（用于菜单第一项）
    private GradientDrawable getTopRoundedDrawable(int color, int radiusDp) {
        float r = dp2px(radiusDp);
        GradientDrawable gd = new GradientDrawable();
        gd.setColor(color);
        // 顺序：左上x2, 右上x2, 右下x2, 左下x2
        gd.setCornerRadii(new float[]{r, r, r, r, r, r, r, r});
        return gd;
    }


    /**
     * 解析接口返回的data数据
     */
    private TruckRouteData parseTruckRouteData(JSONObject data) throws Exception {
        TruckRouteData truckRouteData = new TruckRouteData();

        // 解析truckDto
        if (data.has("truckDto") && !data.isNull("truckDto")) {
            JSONObject truckJson = data.getJSONObject("truckDto");
            TruckDto truckDto = new TruckDto();
            truckDto.isRestriction = truckJson.optBoolean("isRestriction", true);
            truckDto.mvehicleSizeName = truckJson.optString("mvehicleSizeName", "");
            truckDto.mvehicleAxisUnit = truckJson.optString("mvehicleAxisUnit", "轴");
            truckDto.mcarNumber = truckJson.optString("mcarNumber", "");
            truckDto.mcarType = truckJson.optInt("mcarType", 0);
            truckDto.mvehicleHeight = truckJson.optString("mvehicleHeight", "");
            truckDto.mvehicleHeightUnit = truckJson.optString("mvehicleHeightUnit", "M");
            truckDto.mvehicleWeight = truckJson.optString("mvehicleWeight", "");
            truckDto.mvehicleWeightUnit = truckJson.optString("mvehicleWeightUnit", "T");
            truckDto.mvehicleLoad = truckJson.optString("mvehicleLoad", "");
            truckDto.mvehicleLoadUnit = truckJson.optString("mvehicleLoadUnit", "T");
            truckDto.mvehicleLoadSwitch = truckJson.optBoolean("mvehicleLoadSwitch", false);
            truckDto.mvehicleWidth = truckJson.optString("mvehicleWidth", "");
            truckDto.mvehicleWidthUnit = truckJson.optString("mvehicleWidthUnit", "M");
            truckDto.mvehicleLength = truckJson.optString("mvehicleLength", "");
            truckDto.mvehicleLengthUnit = truckJson.optString("mvehicleLengthUnit", "M");
            truckDto.mvehicleSize = truckJson.optInt("mvehicleSize", 2);
            truckDto.mvehicleAxis = truckJson.optInt("mvehicleAxis", 2);
            truckRouteData.truckDto = truckDto;
        }

        // 解析destinationSite
        if (data.has("destinationSite") && !data.isNull("destinationSite")) {
            JSONObject siteJson = data.getJSONObject("destinationSite");
            DestinationSite destinationSite = new DestinationSite();
            destinationSite.innerSiteId = siteJson.optString("innerSiteId", "");
            destinationSite.name = siteJson.optString("name", "");
            destinationSite.shortName = siteJson.optString("shortName", "");
            destinationSite.siteNo = siteJson.optString("siteNo", "");
            destinationSite.city = siteJson.optString("city", "");
            destinationSite.address = siteJson.optString("address", "");
            destinationSite.contact = siteJson.optString("contact", "");
            destinationSite.phone = siteJson.optString("phone", "");
            destinationSite.type = siteJson.optString("type", "");
            destinationSite.coOpMode = siteJson.optString("coOpMode", "");
            destinationSite.booking = siteJson.optString("booking", "");
            destinationSite.siteStatus = siteJson.optString("siteStatus", "");
            destinationSite.siteStatusName = siteJson.optString("siteStatusName", "");
            destinationSite.startBusiness = siteJson.optString("startBusiness", "");
            destinationSite.endBusiness = siteJson.optString("endBusiness", "");
            destinationSite.billingMethod = siteJson.optString("billingMethod", "");
            destinationSite.term = siteJson.optString("term", "");
            destinationSite.remark = siteJson.optString("remark", "");
            destinationSite.longitude = siteJson.optString("longitude", "");
            destinationSite.latitude = siteJson.optString("latitude", "");
            destinationSite.distance = siteJson.optString("distance", "");
            destinationSite.hydrogenPrice = siteJson.optString("hydrogenPrice", "");
            destinationSite.liaisonName = siteJson.optString("liaisonName", "");
            destinationSite.liaisonPhone = siteJson.optString("liaisonPhone", "");
            truckRouteData.destinationSite = destinationSite;
        }

        // 解析pathDto
        if (data.has("pathDto") && !data.isNull("pathDto")) {
            JSONObject pathJson = data.getJSONObject("pathDto");
            PathDto pathDto = new PathDto();
            pathDto.distance = pathJson.optInt("distance", 0);
            pathDto.duration = pathJson.optInt("duration", 0);
            pathDto.strategy = pathJson.optString("strategy", "");
            pathDto.tolls = pathJson.optString("tolls", "");
            pathDto.toll_distance = pathJson.optInt("toll_distance", 0);
            pathDto.restriction = pathJson.optInt("restriction", -1);
            pathDto.traffic_lights = pathJson.optInt("traffic_lights", 0);

            // 解析naviList
            if (pathJson.has("naviList") && !pathJson.isNull("naviList")) {
                JSONArray naviArray = pathJson.getJSONArray("naviList");
                List<NaviPoint> naviList = new ArrayList<>();
                for (int i = 0; i < naviArray.length(); i++) {
                    JSONObject naviJson = naviArray.getJSONObject(i);
                    NaviPoint naviPoint = new NaviPoint();
                    naviPoint.name = naviJson.optString("name", "");
                    naviPoint.poiId = naviJson.optString("poiId", "");

                    if (naviJson.has("coordinate") && !naviJson.isNull("coordinate")) {
                        JSONObject coordJson = naviJson.getJSONObject("coordinate");
                        Coordinate coordinate = new Coordinate();
                        coordinate.longitude = coordJson.optString("longitude", "");
                        coordinate.latitude = coordJson.optString("latitude", "");
                        naviPoint.coordinate = coordinate;
                    }

                    naviList.add(naviPoint);
                }
                pathDto.naviList = naviList;
            }

            truckRouteData.pathDto = pathDto;
        }

        // 解析algorithmPath
        if (data.has("algorithmPath") && !data.isNull("algorithmPath")) {
            JSONObject algorithmJson = data.getJSONObject("algorithmPath");
            AlgorithmPath algorithmPath = new AlgorithmPath();
            algorithmPath.tripRecommendationId = algorithmJson.optString("tripRecommendationId", "");
            algorithmPath.staId = algorithmJson.optString("staId", "");
            algorithmPath.tripOneWayPathId = algorithmJson.optString("tripOneWayPathId", "");
            algorithmPath.tripReturnPathId = algorithmJson.optString("tripReturnPathId", "");
            algorithmPath.oneWayDis = algorithmJson.optString("oneWayDis", "");
            algorithmPath.returnDis = algorithmJson.optString("returnDis", "");
            algorithmPath.roundTripDis = algorithmJson.optString("roundTripDis", "");
            algorithmPath.oneWayTime = algorithmJson.optString("oneWayTime", "");
            algorithmPath.returnTime = algorithmJson.optString("returnTime", "");
            algorithmPath.roundTripTime = algorithmJson.optString("roundTripTime", "");
            algorithmPath.oneWayCost = algorithmJson.optString("oneWayCost", "");
            algorithmPath.returnCost = algorithmJson.optString("returnCost", "");
            algorithmPath.roundTripCost = algorithmJson.optString("roundTripCost", "");
            algorithmPath.oneWayLaborCost = algorithmJson.optString("oneWayLaborCost", "");
            algorithmPath.returnLaborCost = algorithmJson.optString("returnLaborCost", "");
            algorithmPath.roundTripLaborCost = algorithmJson.optString("roundTripLaborCost", "");
            algorithmPath.oneWayChargerouteCost = algorithmJson.optString("oneWayChargerouteCost", "");
            algorithmPath.returnChargerouteCost = algorithmJson.optString("returnChargerouteCost", "");
            algorithmPath.roundTripChargerouteCost = algorithmJson.optString("roundTripChargerouteCost", "");
            algorithmPath.oneWayHydrogenConsumption = algorithmJson.optString("oneWayHydrogenConsumption", "");
            algorithmPath.returnLaborHydrogenConsumption = algorithmJson.optString("returnLaborHydrogenConsumption", "");
            algorithmPath.roundTripHydrogenConsumption = algorithmJson.optString("roundTripHydrogenConsumption", "");
            algorithmPath.oneWayHydrogenCost = algorithmJson.optString("oneWayHydrogenCost", "");
            algorithmPath.returnLaborHydrogenCost = algorithmJson.optString("returnLaborHydrogenCost", "");
            algorithmPath.roundTripHydrogenCost = algorithmJson.optString("roundTripHydrogenCost", "");
            algorithmPath.hydrogenCost = algorithmJson.optString("hydrogenCost", "");
            algorithmPath.hydrogenStaServiceTime = algorithmJson.optString("hydrogenStaServiceTime", "");
            algorithmPath.hydrogenStaRefuelingTime = algorithmJson.optString("hydrogenStaRefuelingTime", "");
            algorithmPath.hydrogenStaQueueTime = algorithmJson.optString("hydrogenStaQueueTime", "");
            algorithmPath.hydrogenStaServiceTimeCost = algorithmJson.optString("hydrogenStaServiceTimeCost", "");
            algorithmPath.hydrogenStaRefuelingTimeCost = algorithmJson.optString("hydrogenStaRefuelingTimeCost", "");
            algorithmPath.hydrogenStaQueueTimeCost = algorithmJson.optString("hydrogenStaQueueTimeCost", "");
            truckRouteData.algorithmPath = algorithmPath;
        }

        // 其他字段
        truckRouteData.truckDtoStr = data.optString("truckDtoStr", null);
        truckRouteData.isInvokeAlgorithm = data.optBoolean("isInvokeAlgorithm", false);

        return truckRouteData;
    }

    // 货车路线算法数据Bean
    public static class TruckRouteData {
        public TruckDto truckDto;
        public String truckDtoStr;
        public DestinationSite destinationSite;
        public PathDto pathDto;
        public AlgorithmPath algorithmPath;
        public boolean isInvokeAlgorithm;
    }

    public static class TruckDto {
        public boolean isRestriction;
        public String mvehicleSizeName;
        public String mvehicleAxisUnit;
        public String mcarNumber;
        public int mcarType;
        public String mvehicleHeight;
        public String mvehicleHeightUnit;
        public String mvehicleWeight;
        public String mvehicleWeightUnit;
        public String mvehicleLoad;
        public String mvehicleLoadUnit;
        public boolean mvehicleLoadSwitch;
        public String mvehicleWidth;
        public String mvehicleWidthUnit;
        public String mvehicleLength;
        public String mvehicleLengthUnit;
        public int mvehicleSize;
        public int mvehicleAxis;
    }

    public static class PathDto {
        public int distance;
        public int duration;
        public String strategy;
        public String tolls;
        public int toll_distance;
        public int restriction;
        public int traffic_lights;
        public List<NaviPoint> naviList;
    }

    public static class NaviPoint {
        public String name;
        public String poiId;
        public Coordinate coordinate;
    }

    public static class Coordinate {
        public String longitude;
        public String latitude;
    }

    public static class AlgorithmPath {
        public String tripRecommendationId;
        public String staId;
        public String tripOneWayPathId;
        public String tripReturnPathId;
        public String oneWayDis;
        public String returnDis;
        public String roundTripDis;
        public String oneWayTime;
        public String returnTime;
        public String roundTripTime;
        public String oneWayCost;
        public String returnCost;
        public String roundTripCost;
        public String oneWayLaborCost;
        public String returnLaborCost;
        public String roundTripLaborCost;
        public String oneWayChargerouteCost;
        public String returnChargerouteCost;
        public String roundTripChargerouteCost;
        public String oneWayHydrogenConsumption;
        public String returnLaborHydrogenConsumption;
        public String roundTripHydrogenConsumption;
        public String oneWayHydrogenCost;
        public String returnLaborHydrogenCost;
        public String roundTripHydrogenCost;
        public String hydrogenCost;
        public String hydrogenStaServiceTime;
        public String hydrogenStaRefuelingTime;
        public String hydrogenStaQueueTime;
        public String hydrogenStaServiceTimeCost;
        public String hydrogenStaRefuelingTimeCost;
        public String hydrogenStaQueueTimeCost;
    }

    public static class DestinationSite {
        public String innerSiteId;
        public String name;
        public String shortName;
        public String siteNo;
        public String city;
        public String address;
        public String contact;
        public String phone;
        public String type;
        public String coOpMode;
        public String booking;
        public String siteStatus;
        public String siteStatusName;
        public String startBusiness;
        public String endBusiness;
        public String billingMethod;
        public String term;
        public String remark;
        public String longitude;
        public String latitude;
        public String distance;

        public String hydrogenPrice;
        public String liaisonName;
        public String liaisonPhone;
    }
}
