<template>
    <div class="edit-map">
        <custom-header @goback="goBack" :isGoBack="true" :name="viewOnly ? '查看区域' : '勾选地块'"></custom-header>
        <div class="region-type-tabs">
            <div v-for="item in regionTypeTabs" :key="item.code" class="region-type-tab"
                :class="{ 'region-type-tab--active': activeRegionType === item.code }"
                @click="handleRegionTypeClick(item)">
                {{ item.name }}
            </div>
        </div>
        <div class="variety-tabs" v-if="varietyTabs.length > 0 && activeRegionType !== 'DORMANCY'">
            <div v-for="(v, index) in varietyTabs" :key="index" class="variety-tab"
                :class="{ 'variety-tab--active': activeVariety === index }" @click="handleVarietyClick(v, index)">
                {{ v.regionName || v.problemZoneTypeName }}
            </div>
        </div>
        <div class="edit-map-content">
            <div class="edit-map-tip" v-if="!viewOnly">操作提示：拖动圆点，即可调整地块边界</div>
            <div class="map-container" ref="mapContainer"></div>
            <div class="edit-map-footer">
                <div v-if="viewOnly" class="footer-back" @click="deletePolygon">
                    <img class="back-icon" src="@/assets/img/map/delete.png" alt="" />
                </div>
                <div class="edit-map-footer-btn" :class="{ 'confirm-btn-box': viewOnly }">
                    <template v-if="!viewOnly">
                        <div class="btn-reset" @click="resetPolygon">重置区域</div>
                        <div class="btn-confirm" @click="openConfirmDrawTypePopup">确认区域</div>
                    </template>
                    <div v-else class="btn-confirm" @click="handleEditRegion">编辑区域</div>
                </div>
            </div>
        </div>
        <tip-popup v-model:show="showTipPopup" type="success" text="您的农情报告已生成" text2="请查看" buttonText="点击查看"
            @confirm="handleTipConfirm" />

        <confirm-draw-type-popup ref="confirmDrawTypePopupRef" @confirm="handleConfirmDrawType" />
    </div>
</template>

<script setup>
import customHeader from "@/components/customHeader.vue";
import { ref, computed, watch, onActivated, onDeactivated, nextTick } from "vue";
import DrawRegionMap from "../../interactionList/map/drawRegionMap.js";
import { Map as KMapMap } from "@/utils/ol-map/KMap";
import { useRouter, useRoute } from "vue-router";
import { convertPointToArray } from "@/utils/index";
import { ElMessage, ElMessageBox } from "element-plus";
import TipPopup from "@/components/popup/tipPopup.vue";
import ConfirmDrawTypePopup from "@/components/popup/confirmDrawTypePopup.vue";
import Style from "ol/style/Style";
import { Fill, Stroke, Circle, Text } from "ol/style.js";
import { Point, Polygon, MultiPolygon } from "ol/geom";
import WKT from "ol/format/WKT.js";
import { unByKey } from "ol/Observable.js";
import * as proj from "ol/proj";
import { getArea } from "ol/sphere.js";

const router = useRouter();
const route = useRoute();
const mapContainer = ref(null);
const drawRegionMap = new DrawRegionMap();

/** OpenLayers 地图在容器尺寸变化后不会自动重算 canvas，需手动 updateSize */
const resizeMapToContainer = () => {
    nextTick(() => {
        requestAnimationFrame(() => {
            drawRegionMap.kmap?.map?.updateSize?.();
        });
    });
};

// handleVarietyClick 内部有延迟渲染（setTimeout），切换查看/编辑或重建地图时必须取消，避免旧回调在新实例上再次 addFeature 造成叠加
const pendingGeomRenderTimer = ref(null);
const clearPendingGeomRenderTimer = () => {
    if (pendingGeomRenderTimer.value) {
        clearTimeout(pendingGeomRenderTimer.value);
        pendingGeomRenderTimer.value = null;
    }
};

const confirmDrawTypePopupRef = ref(null);
const selectedDrawTypeMeta = ref({
    type: "",
    category: "",
    remark: "",
});
// 每个品种（tab）对应的地块数据草稿：key 为 tab index，value 为 { geomArr, geom }（与当前大类 Tab 一致时同步）
const regionsDraftByIndex = ref({});
/** 按弹窗确认的「大类 + 小类」存几何与备注，避免与地图当前选中 Tab 不一致 */
const regionsDraftByKey = ref({});
const submitting = ref(false);
// 仅在首次进入页面时根据路由 varietyId 定位一次，避免后续刷新覆盖当前流程进度
const hasAppliedInitialVariety = ref(false);
const selectedDeleteFeature = ref(null);
const deleteSelectClickKey = ref(null);
const selectedDeleteFeatureUid = ref("");
const selectedDeleteFeatureOriginalStyle = ref(null);

const type = ref(null);
const varietyTabs = ref([]);
const activeVariety = ref(0);
const regionGeom = ref(null);


/** 切换「大类」Tab 时子类列表完全替换，regionsDraftByIndex 按下标缓存会与新区块列表错位；保存成功后也应以接口为准 */
const clearDraftIndexOnly = () => {
    regionsDraftByIndex.value = {};
};

const clearAllRegionDrafts = () => {
    regionsDraftByKey.value = {};
    regionsDraftByIndex.value = {};
};

const clearDeleteSelectionState = () => {
    if (selectedDeleteFeature.value) {
        selectedDeleteFeature.value.setStyle(selectedDeleteFeatureOriginalStyle.value ?? undefined);
        selectedDeleteFeature.value = null;
    }
    selectedDeleteFeatureUid.value = "";
    selectedDeleteFeatureOriginalStyle.value = null;
    if (deleteSelectClickKey.value) {
        unByKey(deleteSelectClickKey.value);
        deleteSelectClickKey.value = null;
    }
};

const getDeleteHighlightStyle = () => {
    const styleKind = getCanonicalRegionTypeForStyles();
    if (styleKind === "variety") {
        return {
            fillColor: "rgba(24, 170, 139, 0.5)",
            strokeColor: "#18AA8B",
        };
    }
    if (styleKind === "ABNORMAL") {
        if (activeVariety.value < 2) {
            return {
                fillColor: "rgba(224, 49, 49, 0.5)",
                strokeColor: "#E03131",
            }
        } else {
            return {
                fillColor: "rgba(255, 115, 0, 0.5)",
                strokeColor: "#FF7300",
            };
        }
    }
    if (styleKind === "ENVIRONMENT") {
        return {
            fillColor: "rgba(255, 199, 102, 0.5)",
            strokeColor: "#FDCF7F",   
        };
    }
    // 其余类型先给默认占位色，后续可按产品视觉再调整
    return {
        fillColor: "rgba(229, 229, 229, 0.5)",
        strokeColor: "#A6A6A6",
    };
};

const highlightDeleteSelectedFeature = (feature) => {
    if (!feature) return;
    if (selectedDeleteFeature.value === feature) return;
    if (selectedDeleteFeature.value && selectedDeleteFeature.value !== feature) {
        selectedDeleteFeature.value.setStyle(selectedDeleteFeatureOriginalStyle.value ?? undefined);
    }
    selectedDeleteFeatureOriginalStyle.value = feature.getStyle ? feature.getStyle() : null;
    selectedDeleteFeature.value = feature;
    selectedDeleteFeatureUid.value = String(feature?.ol_uid || feature?.getId?.() || "");
    const { fillColor, strokeColor } = getDeleteHighlightStyle();
    // 删除选择态：按当前类型动态高亮（单选）
    feature.setStyle(
        new Style({
            fill: new Fill({ color: fillColor }),
            stroke: new Stroke({ color: strokeColor, width: 2 }),
        })
    );
};

const isFeatureLockedForDelete = (feature) => {
    if (activeRegionType.value === "variety") return false;
    const growth = getAbnormalGrowthOverlayMeta(feature);
    const status = String(growth?.handleStatus || "");
    return status === "2" || status === "3";
};

const enableDeleteSelectionMode = () => {
    const map = drawRegionMap.kmap?.map;
    const polygonLayer = drawRegionMap.kmap?.polygonLayer?.layer;
    if (!map || !polygonLayer || deleteSelectClickKey.value) return;
    deleteSelectClickKey.value = map.on("singleclick", (evt) => {
        let hitFeature = null;
        map.forEachFeatureAtPixel(
            evt.pixel,
            (feature) => {
                hitFeature = feature;
                return true;
            },
            {
                layerFilter: (layer) => layer === polygonLayer,
            }
        );
        if (hitFeature) {
            if (isFeatureLockedForDelete(hitFeature)) {
                ElMessage.warning("该地块不可删除");
                return;
            }
            highlightDeleteSelectedFeature(hitFeature);
        }
    });
};

const handleRegionTypeClick = (item) => {
    clearDeleteSelectionState();
    const prevMajor = activeRegionType.value;
    if (item.code !== prevMajor) {
        clearDraftIndexOnly();
    }
    activeRegionType.value = item.code;
    activeVariety.value = 0;
    if (item.code === "variety") {
        varietyTabs.value = regionInfo.value.regionList || [];
    } else {
        varietyTabs.value = item.children;
    }
    handleVarietyClick(varietyTabs.value[activeVariety.value], activeVariety.value);
    if (drawRegionMap.kmap) {
        applyRegionStyles();
    }
};

// 删除当前地块
const deletePolygon = () => {
    const features = drawRegionMap.kmap?.polygonLayer?.source?.getFeatures?.() || [];
    const deletableFeatures = features.filter((f) => !isFeatureLockedForDelete(f));
    let matchedFeature = null;
    if (features.length === 0) {
        clearDeleteSelectionState();
        ElMessage.warning("当前没有可删除的地块");
        return;
    }
    if (features.length === 1 && deletableFeatures.length === 0) {
        clearDeleteSelectionState();
        ElMessage.warning("当前地块不可删除");
        return;
    }
    if (features.length > 1) {
        if (deletableFeatures.length === 0) {
            clearDeleteSelectionState();
            ElMessage.warning("当前地块不可删除");
            return;
        }
        if (!selectedDeleteFeature.value) {
            enableDeleteSelectionMode();
            ElMessage.warning("当前有多个地块，请先选择地块");
            return;
        }
        matchedFeature = features.find((f) => {
            if (f === selectedDeleteFeature.value) return true;
            const uid = String(f?.ol_uid || f?.getId?.() || "");
            return uid && uid === selectedDeleteFeatureUid.value;
        });
        if (!matchedFeature) {
            selectedDeleteFeature.value = null;
            selectedDeleteFeatureUid.value = "";
            ElMessage.warning("请选择地块后再删除");
            return;
        }
        if (isFeatureLockedForDelete(matchedFeature)) {
            clearDeleteSelectionState();
            ElMessage.warning("该地块不可删除");
            return;
        }
    } else {
        clearDeleteSelectionState();
    }

    ElMessageBox.confirm(
        "确认删除当前地块吗？删除后可以重新勾画。",
        "删除确认",
        {
            confirmButtonText: "确认删除",
            cancelButtonText: "取消",
            type: "warning",
        }
    ).then(async () => {
        if (selectedDeleteFeature.value && features.length > 1) {
            drawRegionMap.kmap?.polygonLayer?.source?.removeFeature?.(matchedFeature || selectedDeleteFeature.value);
            clearDeleteSelectionState();
        } else {
            drawRegionMap.deleteCurrentPolygon();
        }

        const polygonData = drawRegionMap.getAreaGeometry?.();
        const geometryArr = polygonData?.geometryArr || [];
        try {
            const ok = await submitCurrentTabGeometryChange(geometryArr);
            if (!ok) {
                ElMessage.error("删除后保存失败");
                return;
            }
            await fetchRegionInfo();
            clearAllRegionDrafts();
            if (activeRegionType.value === "variety") {
                varietyTabs.value = regionInfo.value?.regionList || [];
            } else {
                const group = (regionTypeTabs.value || []).find(
                    (x) => String(x?.code) === String(activeRegionType.value)
                );
                varietyTabs.value = group?.children || [];
            }
            const nextIndex = Math.min(activeVariety.value, Math.max(varietyTabs.value.length - 1, 0));
            activeVariety.value = nextIndex;
            if (varietyTabs.value.length > 0 && varietyTabs.value[nextIndex]) {
                handleVarietyClick(varietyTabs.value[nextIndex], nextIndex);
            } else {
                drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
                drawRegionMap.fitAllRegions?.();
            }
            ElMessage.success("地块已删除");
        } catch (_) {
            ElMessage.error("删除后保存失败");
        }
    });
};

/** 取 Polygon / MultiPolygon 的外环坐标（地图投影），用于顶点样式 */
const getOuterRingCoordinates = (geometry) => {
    if (!geometry || typeof geometry.getType !== "function") return [];
    const type = geometry.getType();
    const c = geometry.getCoordinates();
    if (!c || !c.length) return [];
    if (type === "Polygon") return c[0] || [];
    if (type === "MultiPolygon") return c[0]?.[0] || [];
    return [];
};

const createPolygonStyleFunc = (fillColor, strokeColor) => {
    return (feature) => {
        const growth = getAbnormalGrowthOverlayMeta(feature);
        const isTreatingDisease =
            String(growth?.handleStatus || "") === "2" && !String(growth?.badgeText || "").includes("长势");
        const isTreatingGrowth =
            String(growth?.handleStatus || "") === "2" && String(growth?.badgeText || "").includes("长势");
        const isControlledDisease = String(growth?.handleStatus || "") === "3";
        const currentFillColor = isControlledDisease
            ? SLEEP_ZONE_FILL_COLOR
            : isTreatingGrowth
                ? "rgba(255, 159, 102, 0.3)"
            : isTreatingDisease
                ? DISEASE_TREATING_FILL_COLOR
                : fillColor;
        const currentStrokeColor = isControlledDisease
            ? SLEEP_ZONE_STROKE_COLOR
            : isTreatingGrowth
                ? "rgba(255, 94, 0, 0.3)"
            : isTreatingDisease
                ? DISEASE_TREATING_STROKE_COLOR
                : strokeColor;
        const styles = [];
        const ring = getOuterRingCoordinates(feature.getGeometry());
        const ringLen = ring.length;
        const vertexCount = ringLen > 1 ? ringLen - 1 : ringLen;
        for (let i = 0; i < vertexCount; i++) {
            if (i % 2) {
                styles.push(
                    new Style({
                        geometry: new Point(ring[i]),
                        image: new Circle({
                            radius: 4,
                            fill: new Fill({
                                color: currentStrokeColor,
                            }),
                            stroke: new Stroke({
                                color: "#fff",
                                width: 1,
                            }),
                        }),
                    })
                );
            } else {
                styles.push(
                    new Style({
                        geometry: new Point(ring[i]),
                        image: new Circle({
                            radius: 6,
                            fill: new Fill({
                                color: "#fff",
                            }),
                        }),
                    })
                );
            }
        }
        const fillStyle = new Style({
            fill: new Fill({
                color: currentFillColor,
            }),
            stroke: new Stroke({
                color: currentStrokeColor,
                width: 2,
            }),
        });
        let geom = feature.getGeometry().clone();
        geom.transform(proj.get("EPSG:4326"), proj.get("EPSG:38572"));
        let area = getArea(geom);
        area = (area + area / 2) / 1000;
        if (growth) {
            styles.push(
                new Style({
                    text: new Text({
                        text: growth.badgeText,
                        font: "bold 13px sans-serif",
                        fill: new Fill({ color: growth.badgeTextColor || "#ffffff" }),
                        backgroundFill: new Fill({ color: growth.badgeBackground || ABNORMAL_BADGE_BG_GROWTH }),
                        backgroundStroke: growth.badgeBorderColor
                            ? new Stroke({ color: growth.badgeBorderColor, width: 1 })
                            : undefined,
                        padding: [4, 10, 4, 10],
                        offsetY: -40,
                    }),
                }),
                new Style({
                    text: new Text({
                        text: `发现时间:${growth.discoveryDate}`,
                        font: "12px sans-serif",
                        fill: new Fill({ color: "#ffffff" }),
                        offsetY: -16,
                    }),
                })
            );
        }
        const areaValStyle = new Style({
            text: new Text({
                font: "16px sans-serif",
                text: area.toFixed(2) + "亩",
                fill: new Fill({ color: "#fff" }),
                offsetY: growth ? 14 : 0,
            }),
        });
        styles.push(fillStyle, areaValStyle);
        return styles;
    };
};

const applyRegionStyles = () => {
    const kmap = drawRegionMap.kmap;
    if (!kmap) return;

    let lineColor = "#2199F8";
    let vertexColor = "#2199F8";
    let fillColor = [0, 0, 0, 0.5];
    let strokeColor = "#2199F8";

    const styleKind = getCanonicalRegionTypeForStyles();
    if (styleKind === "variety") {
        lineColor = "#18AA8B";
        vertexColor = "#18AA8B";
        fillColor = [0, 57, 44, 0.5];
        strokeColor = "#18AA8B";
    } else if (styleKind === "ABNORMAL") {
        if (activeVariety.value < 2) {
            lineColor = "#E03131";
            vertexColor = "#E03131";
            fillColor = [100, 0, 0, 0.5];
            strokeColor = "#E03131";
        } else {
            lineColor = "#FF7300";
            vertexColor = "#FF7300";
            fillColor = [124, 46, 0, 0.5];
            strokeColor = "#FF7300";
        }
    } else if (styleKind === "ENVIRONMENT") {
        lineColor = "#FDCF7F";
        vertexColor = "#FDCF7F";
        fillColor = [151, 96, 0, 0.5];
        strokeColor = "#FDCF7F";
    } else {
        lineColor = "#A6A6A6";
        vertexColor = "#A6A6A6";
        fillColor = [166, 166, 166, 0.25];
        strokeColor = "#A6A6A6";
    }


    // 勾画进行中：通过 Map.drawStyleColors 影响底层 drawStyleFunc 颜色
    KMapMap.drawStyleColors = {
        line: lineColor,
        vertex: vertexColor,
        // 只读回显时也复用当前大类颜色（避免查看态全部变绿）
        fill: fillColor,
        stroke: strokeColor,
    };

    kmap.polygonStyle = createPolygonStyleFunc(fillColor, strokeColor);
    if (kmap.polygonLayer?.layer && typeof kmap.polygonLayer.layer.setStyle === "function") {
        kmap.polygonLayer.layer.setStyle(kmap.polygonStyle);
    }
};

const isValidGeom = (geom) => {
    if (typeof geom !== "string") return false;
    const normalized = geom.trim();
    if (!normalized) return false;
    if (["[]", "{}", "null", "undefined", '""'].includes(normalized)) return false;
    return true;
};

/** 与 drawRegionMap / setAreaGeometry 一致：WKT 按 WGS84 解析 */
const WGS84_WKT_OPTS = Object.freeze({
    dataProjection: "EPSG:4326",
    featureProjection: "EPSG:4326",
});

const wktGeomFormat = new WKT();

/** Polygon / MultiPolygon 各自对应一组环坐标（MultiPolygon 为多块） */
const polygonCoordSetsFromGeometry = (geometry) => {
    if (!geometry || typeof geometry.getType !== "function") return [];
    const type = geometry.getType();
    if (type === "Polygon") return [geometry.getCoordinates()];
    if (type === "MultiPolygon") return geometry.getCoordinates();
    return [];
};

const mergePolygonWktsForApi = (wktArr) => {
    if (!Array.isArray(wktArr) || wktArr.length === 0) return "";
    const trimmed = wktArr.map((x) => String(x).trim()).filter(isValidGeom);
    if (trimmed.length === 0) return "";
    if (trimmed.length === 1) return trimmed[0];

    const coordSets = [];
    for (const w of trimmed) {
        try {
            const g = wktGeomFormat.readGeometry(w, WGS84_WKT_OPTS);
            coordSets.push(...polygonCoordSetsFromGeometry(g));
        } catch (_) {
            /* 单条解析失败则跳过 */
        }
    }
    if (coordSets.length === 0) return trimmed[0];
    if (coordSets.length === 1) {
        try {
            return wktGeomFormat.writeGeometry(new Polygon(coordSets[0]), WGS84_WKT_OPTS);
        } catch (_) {
            return trimmed[0];
        }
    }
    return wktGeomFormat.writeGeometry(new MultiPolygon(coordSets), WGS84_WKT_OPTS);
};

const flattenWktToPolygonWktArray = (wkt) => {
    if (!isValidGeom(wkt)) return [];
    const s = String(wkt).trim();
    try {
        const g = wktGeomFormat.readGeometry(s, WGS84_WKT_OPTS);
        const sets = polygonCoordSetsFromGeometry(g);
        if (sets.length === 0) return [s];
        return sets.map((rings) => wktGeomFormat.writeGeometry(new Polygon(rings), WGS84_WKT_OPTS));
    } catch (_) {
        return [s];
    }
};

const flattenGeomWktList = (arr) => {
    if (!Array.isArray(arr)) return [];
    const out = [];
    for (const item of arr) {
        if (!isValidGeom(item)) continue;
        out.push(...flattenWktToPolygonWktArray(String(item).trim()));
    }
    return out;
};

/** 地图回显：展开 MULTIPOLYGON 为多个 POLYGON WKT，并去掉无效项 */
const flattenGeomWktListForMap = (arr) => flattenGeomWktList(arr).filter(isValidGeom);

const formatAreaTextFromGeomArr = (geomWktArr) => {
    if (!Array.isArray(geomWktArr) || geomWktArr.length === 0) return "";
    let totalArea = 0;
    for (const wkt of geomWktArr) {
        if (!isValidGeom(wkt)) continue;
        try {
            const geometry = wktGeomFormat.readGeometry(String(wkt).trim(), WGS84_WKT_OPTS);
            geometry.transform(proj.get("EPSG:4326"), proj.get("EPSG:38572"));
            let area = getArea(geometry);
            area = (area + area / 2) / 1000;
            totalArea += Number(area) || 0;
        } catch (_) {
            /* 单条解析失败则跳过 */
        }
    }
    return totalArea > 0 ? `${totalArea.toFixed(2)}亩` : "";
};

// 从 tab.geomItems[{geomWkt}] 中提取 WKT 数组（兼容单块/多块）
const getGeomArrFromGeomItems = (tab) => {
    const items = tab?.geomItems;
    if (!Array.isArray(items) || items.length === 0) return [];
    return items
        .map((x) => x?.geomWkt)
        .filter((x) => x !== undefined && x !== null)
        .map((x) => String(x).trim())
        .filter((x) => isValidGeom(x));
};

const isDiseaseAbnormalTab = (tab) => {
    const name = (tab?.problemZoneTypeName || tab?.regionName || "").toString();
    return name.includes("病害") || name.includes("虫害");
};

const isGrowthAbnormalTab = (tab) => {
    const name = (tab?.problemZoneTypeName || tab?.regionName || "").toString();
    return name.includes("过慢") || name.includes("过快");
};

const hasLockedStatusItems = (tab) => {
    const items = Array.isArray(tab?.geomItems) ? tab.geomItems : [];
    return items.some((item) => {
        const status = String(item?.handleStatus ?? "");
        return status === "2" || status === "3";
    });
};

const isLockedAbnormalTab = (tab) =>
    isDiseaseAbnormalTab(tab) || isGrowthAbnormalTab(tab) || hasLockedStatusItems(tab);

const isLockedAbnormalItem = (tab, item) => {
    const status = String(item?.handleStatus ?? "");
    if (!isLockedAbnormalTab(tab)) return false;
    return status === "2" || status === "3";
};

const formatDateToYmdDot = (raw) => {
    const sourceDate = raw ? new Date(raw) : new Date();
    const resolvedDate = Number.isNaN(sourceDate.getTime()) ? new Date() : sourceDate;
    const y = resolvedDate.getFullYear();
    const m = String(resolvedDate.getMonth() + 1).padStart(2, "0");
    const d = String(resolvedDate.getDate()).padStart(2, "0");
    return `${y}.${m}.${d}`;
};

const formatDateToYmdDash = (raw) => {
    const sourceDate = raw ? new Date(raw) : new Date();
    const resolvedDate = Number.isNaN(sourceDate.getTime()) ? new Date() : sourceDate;
    const y = resolvedDate.getFullYear();
    const m = String(resolvedDate.getMonth() + 1).padStart(2, "0");
    const d = String(resolvedDate.getDate()).padStart(2, "0");
    return `${y}-${m}-${d}`;
};

const getLockedDiseaseRegions = (tab) => {
    if (!isLockedAbnormalTab(tab)) return [];
    const items = Array.isArray(tab?.geomItems) ? tab.geomItems : [];
    const out = [];
    items.forEach((item) => {
        if (!isLockedAbnormalItem(tab, item)) return;
        const status = String(item?.handleStatus ?? "");
        const polygons = flattenWktToPolygonWktArray(item?.geomWkt).filter(isValidGeom);
        polygons.forEach((geometry) => {
            const name = (tab?.problemZoneTypeName || tab?.regionName || "").toString();
            const isGrowth = name.includes("过慢") || name.includes("过快");
            const prefix = name.includes("虫害")
                ? "虫害"
                : name.includes("病害")
                    ? "病害"
                    : name.includes("过快")
                        ? "长势过快"
                        : "长势过慢";
            out.push({
                geometry,
                displayMode: "lockedDisease",
                handleStatus: status,
                lockStyleType: isGrowth ? "growthTreating" : status === "3" ? "controlled" : "diseaseTreating",
                label: status === "3" ? `${prefix}已控制` : `${prefix}治疗中`,
                updatedTime: formatDateToYmdDot(item?.createTime),
            });
        });
    });
    return out;
};

const getEditableGeomArrForCurrentTab = (tab, rawGeomArr) => {
    if (
        !tab ||
        !isLockedAbnormalTab(tab) ||
        viewOnly.value ||
        activeRegionType.value === "variety"
    ) {
        return flattenGeomWktListForMap(rawGeomArr);
    }
    const key = draftKeyFromParts(activeRegionType.value, tab);
    const draft = key ? regionsDraftByKey.value[key] : null;
    const draftItems = Array.isArray(draft?.geomItems) ? draft.geomItems : [];
    const items = draftItems.length > 0 ? draftItems : Array.isArray(tab?.geomItems) ? tab.geomItems : [];
    const editable = [];
    items.forEach((item) => {
        if (isLockedAbnormalItem(tab, item)) return;
        editable.push(...flattenWktToPolygonWktArray(item?.geomWkt));
    });
    const editableGeomArr = flattenGeomWktListForMap(editable);
    if (editableGeomArr.length > 0) return editableGeomArr;
    // 当前小类存在 2/3 锁定地块时，编辑图层保持空，避免把锁定地块误加到可编辑层
    const hasLockedItems = items.some((item) => isLockedAbnormalItem(tab, item));
    if (hasLockedItems) return [];
    // 仅当无锁定地块且没有 geomItems 时，兜底使用纯几何草稿（例如新勾画未落库）
    const draftGeom = getDraftGeomForTab(activeRegionType.value, tab, activeVariety.value);
    if (isValidGeom(draftGeom)) {
        return flattenGeomWktListForMap([String(draftGeom).trim()]);
    }
    return editableGeomArr;
};

// 兜底防线：若锁定地块意外进入可编辑图层，按 handleStatus(2/3) 强制移除，避免只读层与可编辑层叠加
const purgeLockedFeaturesFromEditableLayer = (tab) => {
    if (!isLockedAbnormalTab(tab)) return;
    const source = drawRegionMap.kmap?.polygonLayer?.source;
    if (!source) return;
    const features = source.getFeatures?.() || [];
    features.forEach((feature) => {
        const geomItem = getGeomItemByFeature(tab, feature);
        const status = String(geomItem?.handleStatus ?? "");
        if (status === "2" || status === "3") {
            source.removeFeature?.(feature);
        }
    });
};

/** 非品种区提交：按当前地块顺序生成 geomItems（已有项更新，新项追加） */
const buildGeomItemsFromGeometryArr = (tab, geometryArr, remarkOverride) => {
    const geomArr = flattenGeomWktListForMap(geometryArr || []);
    const existingItems = Array.isArray(tab?.geomItems) ? tab.geomItems : [];
    const nowDate = new Date();
    const y = nowDate.getFullYear();
    const m = String(nowDate.getMonth() + 1).padStart(2, "0");
    const d = String(nowDate.getDate()).padStart(2, "0");
    const defaultCreateTime = `${y}-${m}-${d}`;
    return geomArr.map((geomWkt, idx) => {
        const base = existingItems[idx] && typeof existingItems[idx] === "object" ? existingItems[idx] : {};
        const baseRemark = base?.remark != null ? String(base.remark) : "";
        const finalRemark = remarkOverride != null ? String(remarkOverride) : baseRemark;
        const createTime =
            base?.createTime != null && String(base.createTime).trim() !== ""
                ? String(base.createTime)
                : defaultCreateTime;
        const handleStatus =
            base?.handleStatus != null && String(base.handleStatus).trim() !== ""
                ? base.handleStatus
                : 1;
        return {
            ...base,
            geomWkt,
            remark: finalRemark,
            createTime,
            handleStatus,
        };
    });
};

/** 病害编辑态提交：2/3 保持只读原样，1 与新勾画项按当前可编辑地块更新/追加 */
const buildDiseaseGeomItemsForSubmit = (tab, editableGeometryArr, remarkOverride) => {
    const items = Array.isArray(tab?.geomItems) ? tab.geomItems : [];
    const lockedItems = items
        .filter((item) => {
            const status = String(item?.handleStatus ?? "");
            return status === "2" || status === "3";
        })
        .map((item) => ({
            ...item,
            geomWkt: isValidGeom(item?.geomWkt) ? String(item.geomWkt).trim() : "",
            remark: item?.remark != null ? String(item.remark) : "",
        }))
        .filter((item) => isValidGeom(item.geomWkt));
    const editableBaseItems = items.filter((item) => {
        const status = String(item?.handleStatus ?? "");
        return status === "1" || status === "";
    });
    const geomArr = flattenGeomWktListForMap(editableGeometryArr || []);
    const editableItems = geomArr.map((geomWkt, idx) => {
        const base =
            editableBaseItems[idx] && typeof editableBaseItems[idx] === "object"
                ? editableBaseItems[idx]
                : {};
        const baseRemark = base?.remark != null ? String(base.remark) : "";
        const finalRemark = remarkOverride != null ? String(remarkOverride) : baseRemark;
        const createTime =
            base?.createTime != null && String(base.createTime).trim() !== ""
                ? String(base.createTime)
                : formatDateToYmdDot();
        const handleStatus =
            base?.handleStatus != null && String(base.handleStatus).trim() !== ""
                ? String(base.handleStatus)
                : 1;
        return {
            ...base,
            geomWkt,
            remark: finalRemark,
            createTime: formatDateToYmdDash(createTime),
            handleStatus,
        };
    });
    return [...lockedItems, ...editableItems];
};

const draftKeyFromParts = (majorType, tabLike) => {
    if (!majorType || !tabLike || typeof tabLike !== "object") return "";
    const t = tabLike;
    const id = t.regionId ?? t.problemZoneTypeId ?? t.typeId ?? t.id;
    if (id != null && String(id).trim() !== "") {
        return `${majorType}:${String(id).trim()}`;
    }
    const nm = (t.regionName || t.problemZoneTypeName || "").toString().trim();
    return nm ? `${majorType}:name:${nm}` : "";
};

const getDraftGeomForTab = (majorType, tab, index) => {
    const k = draftKeyFromParts(majorType, tab);
    const byKey = k ? regionsDraftByKey.value[k] : null;
    if (byKey?.geom) return byKey.geom;
    return regionsDraftByIndex.value[index]?.geom;
};

const resolveInitialVarietyIndex = (regionList) => {
    const queryVarietyId = route.query?.varietyId;
    if (!queryVarietyId || !Array.isArray(regionList) || regionList.length === 0) return 0;
    const queryId = String(queryVarietyId).trim();
    const matchedIndex = regionList.findIndex((item) => {
        const candidateIds = [item?.typeId, item?.varietyId, item?.id]
            .filter((v) => v !== undefined && v !== null)
            .map((v) => String(v).trim());
        return candidateIds.includes(queryId);
    });
    return matchedIndex >= 0 ? matchedIndex : 0;
};

const getReadonlyVarietyRegions = (activeIndex) => {
    if (!Array.isArray(varietyTabs.value) || varietyTabs.value.length === 0) return [];
    const readonlyRegions = [];
    for (let i = 0; i < varietyTabs.value.length; i++) {
        if (i === activeIndex) continue;
        const tab = varietyTabs.value[i];
        if (!tab) continue;
        const draftGeom = getDraftGeomForTab(activeRegionType.value, tab, i);
        const geometry = draftGeom || tab.geom;
        if (!isValidGeom(geometry)) continue;
        readonlyRegions.push({
            geometry,
            label: tab.regionName || "",
            displayMode: "readonlyVariety",
        });
    }
    return readonlyRegions;
};

const getAllVarietyReadonlyRegions = () => {
    const list = regionInfo.value?.regionList || [];
    if (!Array.isArray(list) || list.length === 0) return [];
    const regions = [];
    for (let i = 0; i < list.length; i++) {
        const tab = list[i];
        if (!tab) continue;
        const draftGeom = getDraftGeomForTab("variety", tab, i);
        const geometry = draftGeom || tab.geom;
        if (!isValidGeom(geometry)) continue;
        regions.push({
            geometry,
            label: tab.regionName || "",
            displayMode: "readonlyVariety",
        });
    }
    return regions;
};

const renderReadonlyVarietyRegions = (activeIndex) => {
    if (drawRegionMap && typeof drawRegionMap.setStatusRegions === "function") {
        drawRegionMap.setStatusRegions(getReadonlyVarietyRegions(activeIndex));
    }
};

/**
 * 仅渲染「品种区」所有已有地块（只读），用于在其它问题区查看/编辑时作为底图参考。
 * 需求：只显示品种区地块，其它问题区地块不显示，且不可编辑。
 */
const renderAllVarietyRegionsReadonlyOnly = () => {
    if (!drawRegionMap || typeof drawRegionMap.setStatusRegions !== "function") return;
    const regions = getAllVarietyReadonlyRegions();
    if (regions.length === 0) {
        drawRegionMap.setStatusRegions([]);
        return;
    }
    drawRegionMap.setStatusRegions(regions);
};

/**
 * 用户“闭环(drawend)”后，把当前绘制结果自动写入草稿，避免切换 tab 时被清掉。
 * 注意：getAreaGeometry 可能包含多块，这里以“最新一块”为准（最后一个 feature）
 */
const syncClosedDrawToDraft = () => {
    const tab = varietyTabs.value?.[activeVariety.value];
    if (!tab) return;
    const polygonData = drawRegionMap.getAreaGeometry?.();
    const geometryArr = polygonData?.geometryArr;
    if (!Array.isArray(geometryArr) || geometryArr.length === 0) return;
    const geom = String(geometryArr[geometryArr.length - 1] || "").trim();
    if (!isValidGeom(geom)) return;

    const key = draftKeyFromParts(activeRegionType.value, tab);
    if (key) {
        const prev = regionsDraftByKey.value[key] || {};
        regionsDraftByKey.value[key] = {
            ...prev,
            geomArr: [geom],
            geom,
        };
    }
    regionsDraftByIndex.value[activeVariety.value] = { geomArr: [geom], geom };
    regionGeom.value = geom;
};

const handleVarietyClick = (tab, index) => {
    clearDeleteSelectionState();
    // 取消上一次延迟渲染，避免快速切换 tab / 切换编辑态时重复追加要素
    clearPendingGeomRenderTimer();

    // 若存在“未闭环”的绘制草图（Draw 的 sketch 在 overlay 上），切换时需要清掉；已闭环的要素会走 drawend 写入草稿
    const draw = drawRegionMap.kmap?.draw;
    const hasUnclosedSketch = !!(draw && (draw.sketchFeature_ || draw.sketchCoords_ || draw.sketchLine_));
    if (hasUnclosedSketch) {
        drawRegionMap.abortOngoingDrawSketch?.();
    }

    activeVariety.value = index;
    // 取值优先级：
    // 1) 草稿（regionsDraftByKey / regionsDraftByIndex）
    // 2) 接口返回的 tab.geomItems[].geomWkt（你给的结构）
    // 3) 兜底 tab.geom（兼容旧结构）
    const draftGeom = getDraftGeomForTab(activeRegionType.value, tab, index);
    const rawGeomArr =
        isValidGeom(draftGeom)
            ? [String(draftGeom).trim()]
            : (() => {
                const fromItems = getGeomArrFromGeomItems(tab);
                if (fromItems.length) return fromItems;
                return isValidGeom(tab?.geom) ? [String(tab.geom).trim()] : [];
            })();
    const geomArr = getEditableGeomArrForCurrentTab(tab, rawGeomArr);
    // 保留一份“当前选中地块”的原始字符串形态给其它逻辑使用
    regionGeom.value = geomArr.length > 1 ? JSON.stringify(geomArr) : geomArr[0] || "";
    // 地图尚未初始化时，仅更新状态，不做图层绘制，避免首次进入重复叠加
    if (!drawRegionMap.kmap) return;

    // 确保当前大类颜色样式生效（非品种区：黄色/红色/灰色；品种区：绿色）
    applyRegionStyles();

    // 非品种区：底图显示品种区（只读绿色）+ 当前小类（按当前大类颜色渲染）
    // 品种区：显示其他品种只读 + 当前品种可编辑
    if (activeRegionType.value !== "variety") {
        if (isLockedAbnormalTab(tab)) {
            drawRegionMap.setStatusRegions([
                ...getAllVarietyReadonlyRegions(),
                ...getLockedDiseaseRegions(tab),
            ]);
            // 查看态也需要继续渲染当前小类地块（handleStatus=1），
            // 2/3 锁定地块仍由 setStatusRegions 只读层承载，避免被遗漏
        } else {
            renderAllVarietyRegionsReadonlyOnly();
        }
    } else {
        renderReadonlyVarietyRegions(index);
    }

    // 切换时先清空当前可编辑图层，避免叠加
    drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
    if (geomArr.length > 0) {
        pendingGeomRenderTimer.value = setTimeout(() => {
            // 再兜底清一次，避免异步回调在 destroy/init 后仍执行导致重复追加
            drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
            const viewOnlySubCategoryLabel =
                route.query.type === "viewOnly" && getCanonicalRegionTypeForStyles() !== "ABNORMAL"
                    ? (tab.regionName || tab.problemZoneTypeName || "").toString().trim()
                    : "";
            const currentAreaText = formatAreaTextFromGeomArr(geomArr);
            const viewOnlySubCategoryLabelWithArea =
                viewOnlySubCategoryLabel && currentAreaText
                    ? `${viewOnlySubCategoryLabel}\n${currentAreaText}`
                    : viewOnlySubCategoryLabel;
            drawRegionMap.setAreaGeometry(
                geomArr,
                false,
                undefined,
                undefined,
                getAbnormalGrowthOverlayMeta,
                viewOnlySubCategoryLabelWithArea || undefined
            );
            if (!viewOnly.value && activeRegionType.value !== "variety") {
                purgeLockedFeaturesFromEditableLayer(tab);
            }
            // 有当前小类地块：仅 fit 当前可编辑层，避免被其它只读参考地块拉远
            drawRegionMap.fitView?.();
        }, 50);
    } else {
        // 当前小类无地块：视野包含品种区只读底图（与其它参考地块联合范围）
        pendingGeomRenderTimer.value = setTimeout(() => {
            drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
            drawRegionMap.fitAllRegions?.();
        }, 50);
    }
};

const viewOnly = computed(() => route.query.type === "viewOnly");

const point = ref(null);

const regionTypeTabs = ref([]);
const activeRegionType = ref("variety");
const regionInfo = ref([]);
async function fetchRegionInfo() {
    const { data } = await VE_API.basic_farm.fetchRegionInfo({ subjectId: route.query.subjectId });
    if (data && data.length > 0) {
        regionInfo.value = data[0] || [];
        regionTypeTabs.value = regionInfo.value.problemZoneList || [];
        regionTypeTabs.value.unshift({ name: "品种区", code: "variety" });
        if (data[0]?.regionList?.length) {
            if (!hasAppliedInitialVariety.value && route.query?.varietyId) {
                activeVariety.value = resolveInitialVarietyIndex(data[0]?.regionList);
                hasAppliedInitialVariety.value = true;
            }

            point.value = data[0].point;

            varietyTabs.value = regionInfo.value.regionList || [];
        }
    }
}

/** 样式用的大类：与接口 tab.code 解耦（避免 ABNORMAL / 数字 code 等导致勾画色落到默认灰） */
const getCanonicalRegionTypeForStyles = () => {
    const raw = activeRegionType.value;
    if (raw === "variety") return "variety";
    const tabs = regionTypeTabs.value || [];
    const item = tabs.find((t) => String(t?.code) === String(raw));
    if (item) {
        const kind = item.code;
        if (kind) return kind;
    }
    return "SLEEP";
};

const ABNORMAL_BADGE_BG_DISEASE_PEST = "#E32A28";
const ABNORMAL_BADGE_BG_GROWTH = "#F76F00";
const DISEASE_TREATING_FILL_COLOR = "rgba(191, 91, 91, 0.36)";
const DISEASE_TREATING_STROKE_COLOR = "rgba(224, 49, 49, 0.3)";
const SLEEP_ZONE_STROKE_COLOR = "#A6A6A6";
const SLEEP_ZONE_FILL_COLOR = [166, 166, 166, 0.25];

const getGeomItemByFeature = (tab, feature) => {
    if (!tab || !feature) return null;
    const items = Array.isArray(tab.geomItems) ? tab.geomItems : [];
    if (!items.length) return null;
    let featureWkt = "";
    try {
        featureWkt = wktGeomFormat.writeGeometry(feature.getGeometry(), WGS84_WKT_OPTS);
    } catch (_) {
        featureWkt = "";
    }
    if (!isValidGeom(featureWkt)) return null;
    const normalizeWktKey = (wkt) => String(wkt || "").replace(/\s+/g, "").trim();
    const normalizedFeatureWkt = normalizeWktKey(featureWkt);
    for (const item of items) {
        const polygons = flattenWktToPolygonWktArray(item?.geomWkt);
        if (polygons.some((w) => normalizeWktKey(w) === normalizedFeatureWkt)) {
            return item;
        }
    }
    // 兜底：仅在要素数量与 geomItems 数量一致时按索引映射，避免病害锁定态错位
    const features = drawRegionMap.kmap?.polygonLayer?.source?.getFeatures?.() || [];
    if (features.length === items.length) {
        const featureIndex = features.findIndex((f) => f === feature);
        if (featureIndex >= 0 && featureIndex < items.length) {
            return items[featureIndex];
        }
    }
    return null;
};

/** 异常区小类（长势/病害/虫害等）闭合地块后在多边形内展示标签与发现日期（查看态 setAreaGeometry 同步使用） */
const getAbnormalGrowthOverlayMeta = (feature) => {
    if (getCanonicalRegionTypeForStyles() !== "ABNORMAL") return null;
    const tab = varietyTabs.value?.[activeVariety.value];
    if (!tab) return null;
    const geomItem = getGeomItemByFeature(tab, feature);
    const name = (tab.problemZoneTypeName || tab.regionName || "").toString();
    const handleStatus = String(geomItem?.handleStatus || "");
    let badgeText = "";
    let badgeBackground = ABNORMAL_BADGE_BG_GROWTH;
    let badgeTextColor = "#ffffff";
    let badgeBorderColor = "";
    if (name.includes("病害") || name.includes("虫害")) {
        // 病害/虫害：严格按当前地块对应 geomItem；未命中（新勾画）按“新增”展示，避免误用旧地块状态
        const currentGeomItem = geomItem || null;
        const currentHandleStatus = String(currentGeomItem?.handleStatus || "");
        const currentCreateTime = currentGeomItem?.createTime;
        const prefix = name.includes("虫害") ? "虫害" : "病害";
        if (!currentGeomItem) {
            badgeText = `新增${prefix}`;
            badgeBackground = ABNORMAL_BADGE_BG_DISEASE_PEST;
        } else if (currentHandleStatus === "2") {
            badgeText = `${prefix}治疗中`;
            badgeTextColor = ABNORMAL_BADGE_BG_DISEASE_PEST;
            badgeBackground = "#fff";
            badgeBorderColor = ABNORMAL_BADGE_BG_DISEASE_PEST;
        } else if (currentHandleStatus == "3") {
            badgeText = `${prefix}已控制`;
            // 已控制态与休眠区视觉保持一致
            badgeBackground = SLEEP_ZONE_STROKE_COLOR;
        } else {
            badgeText = `新增${prefix}`;
            badgeBackground = ABNORMAL_BADGE_BG_DISEASE_PEST;
        }
        const rawCreateTime = currentCreateTime || tab?.createTime;
        const sourceDate = rawCreateTime ? new Date(rawCreateTime) : new Date();
        const resolvedDate = Number.isNaN(sourceDate.getTime()) ? new Date() : sourceDate;
        const y = resolvedDate.getFullYear();
        const m = String(resolvedDate.getMonth() + 1).padStart(2, "0");
        const d = String(resolvedDate.getDate()).padStart(2, "0");
        return {
            badgeText,
            discoveryDate: `${y}.${m}.${d}`,
            badgeBackground,
            badgeTextColor,
            badgeBorderColor,
            handleStatus: currentHandleStatus,
        };
    } else if (name.includes("过慢")) {
        if (handleStatus === "2") {
            badgeText = "长势过慢治疗中";
            badgeTextColor = ABNORMAL_BADGE_BG_GROWTH;
            badgeBackground = "#fff";
            badgeBorderColor = ABNORMAL_BADGE_BG_GROWTH;
        } else {
            badgeText = "新增长势过慢";
        }
    } else if (name.includes("过快")) {
        if (handleStatus === "2") {
            badgeText = "长势过快治疗中";
            badgeTextColor = ABNORMAL_BADGE_BG_GROWTH;
            badgeBackground = "#fff";
            badgeBorderColor = ABNORMAL_BADGE_BG_GROWTH;
        } else {
            badgeText = "新增长势过快";
        }
    } else {
        return null;
    }
    const rawCreateTime = geomItem?.createTime || tab?.createTime;
    const sourceDate = rawCreateTime ? new Date(rawCreateTime) : new Date();
    const resolvedDate = Number.isNaN(sourceDate.getTime()) ? new Date() : sourceDate;
    const y = resolvedDate.getFullYear();
    const m = String(resolvedDate.getMonth() + 1).padStart(2, "0");
    const d = String(resolvedDate.getDate()).padStart(2, "0");
    return {
        badgeText,
        discoveryDate: `${y}.${m}.${d}`,
        badgeBackground,
        badgeTextColor,
        badgeBorderColor,
        handleStatus,
    };
};

const findProblemZoneGroupByDrawType = (majorType) => {
    if (!majorType || majorType === "variety") return null;
    const list = regionInfo.value?.problemZoneList || [];
    return (
        list.find((x) => x.code === majorType) ||
        list.find((x) => String(x?.code) === String(majorType))
    );
};

const getTabsForMajorType = (majorType) => {
    if (majorType === "variety") {
        return regionInfo.value?.regionList || [];
    }
    const g = findProblemZoneGroupByDrawType(majorType);
    return g?.children || [];
};

const findTabIndexForCategory = (tabs, category) => {
    if (!Array.isArray(tabs) || !category || typeof category !== "object") return -1;
    const fields = ["regionId", "problemZoneTypeId", "typeId", "id"];
    for (let i = 0; i < tabs.length; i++) {
        const t = tabs[i];
        for (const f of fields) {
            const cv = category[f];
            const tv = t[f];
            if (cv != null && cv !== "" && tv != null && String(cv) === String(tv)) return i;
        }
    }
    const cname = (category.regionName || category.problemZoneTypeName || "").toString().trim();
    if (cname) {
        const idx = tabs.findIndex((t) => {
            const tn = (t.regionName || t.problemZoneTypeName || "").toString().trim();
            return tn === cname;
        });
        if (idx >= 0) return idx;
    }
    return -1;
};

/** 仅提交本次有勾画草稿（regionsDraftByKey）的品种区，不带未勾画项 */
const buildRegionListForSubmit = () => {
    const list = regionInfo.value?.regionList || [];
    const out = [];
    list.forEach((tab) => {
        const k = draftKeyFromParts("variety", tab);
        const d = k ? regionsDraftByKey.value[k] : null;
        const geom = d?.geom != null ? String(d.geom).trim() : "";
        if (!isValidGeom(geom)) return;
        out.push({
            regionId: tab.regionId,
            typeId: tab.typeId,
            regionName: tab.regionName,
            geom,
        });
    });
    return out;
};

/** 仅包含有勾画草稿的问题分区子项；无任何子项勾画的分组整组不传 */
const buildProblemZoneListForSubmit = () => {
    const raw = regionInfo.value?.problemZoneList || [];
    const subjectId = route.query.subjectId;
    const groups = [];
    raw.forEach((group) => {
        const canonical = group.code;
        const children = (group.children || [])
            .map((child) => {
                if (!canonical) return null;
                const k = draftKeyFromParts(canonical, child);
                const d = k ? regionsDraftByKey.value[k] : null;
                let geomItems = Array.isArray(d?.geomItems)
                    ? d.geomItems
                    : [];
                geomItems = geomItems
                    .map((x) => {
                        const geomWkt = x?.geomWkt != null ? String(x.geomWkt).trim() : "";
                        if (!isValidGeom(geomWkt)) return null;
                        return {
                            ...x,
                            geomWkt,
                            remark: x?.remark != null ? String(x.remark) : "",
                        };
                    })
                    .filter(Boolean);
                if (geomItems.length === 0) {
                    const geomWkt = d?.geom != null ? String(d.geom).trim() : "";
                    if (!isValidGeom(geomWkt)) return null;
                    const remark =
                        d && "remark" in d && d.remark != null ? String(d.remark) : "";
                    geomItems = [{ geomWkt, remark }];
                }
                return {
                    farmSubjectId: subjectId,
                    problemZoneTypeId: child.problemZoneTypeId ?? child.typeId ?? "",
                    problemZoneTypeName: child.problemZoneTypeName ?? child.regionName ?? "",
                    parentName: group.name ?? "",
                    parentCode: group.code ?? "",
                    geomItems,
                };
            })
            .filter(Boolean);
        if (children.length === 0) return;
        groups.push({
            name: group.name,
            code: group.code,
            children,
        });
    });
    return groups;
};

onActivated(async () => {
    activeVariety.value = 0;
    hasAppliedInitialVariety.value = false;
    clearPendingGeomRenderTimer();
    // keep-alive 场景下再次进入前先销毁旧地图实例，避免重复 init 导致图层状态错位
    if (drawRegionMap.kmap) {
        drawRegionMap.abortOngoingDrawSketch?.();
        drawRegionMap.destroyMap?.();
    }

    type.value = route.query.type;
    const editable = !viewOnly.value;
    await fetchRegionInfo();
    drawRegionMap.initMap(point.value, mapContainer.value, editable, true, true, syncClosedDrawToDraft);
    applyRegionStyles();

    // 首次进入时，fetch 阶段可能先于地图初始化触发了 tab 渲染；
    // 这里在地图可用后再补渲一次，确保“其他品种只读地块”能显示出来
    if (varietyTabs.value.length > 0 && varietyTabs.value[activeVariety.value]) {
        handleVarietyClick(varietyTabs.value[activeVariety.value], activeVariety.value);
    }


    // 从编辑态进入仅查看时，需重新初始化为不可编辑
    if (viewOnly.value && drawRegionMap.kmap && drawRegionMap.editable) {
        drawRegionMap.destroyMap();
        drawRegionMap.initMap(point.value, mapContainer.value, false, true, false, syncClosedDrawToDraft);
        applyRegionStyles();
        if (varietyTabs.value.length > 0 && varietyTabs.value[activeVariety.value]) {
            handleVarietyClick(varietyTabs.value[activeVariety.value], activeVariety.value);
        }
    }

    // 从仅查看进入勾画（编辑）时，需重新初始化为可编辑
    if (!viewOnly.value && drawRegionMap.kmap && !drawRegionMap.editable) {
        drawRegionMap.destroyMap();
        drawRegionMap.initMap(point.value, mapContainer.value, true, true, true, syncClosedDrawToDraft);
        applyRegionStyles();
        if (varietyTabs.value.length > 0 && varietyTabs.value[activeVariety.value]) {
            handleVarietyClick(varietyTabs.value[activeVariety.value], activeVariety.value);
        }
    }

    // 查看模式下已通过 fitAllRegions 适配；编辑模式再设置地图中心
    if (!viewOnly.value) {
        drawRegionMap.setMapPosition(convertPointToArray(point.value));
    }

    resizeMapToContainer();
});

watch(
    () => [varietyTabs.value.length, activeRegionType.value, activeVariety.value],
    () => {
        if (drawRegionMap.kmap?.map) resizeMapToContainer();
    }
);

onDeactivated(() => {
    clearDeleteSelectionState();
    activeVariety.value = 0;
    activeRegionType.value = "variety";
    clearPendingGeomRenderTimer();
    // 离开页面时中止未完成绘制并销毁地图，确保下次进入是干净实例
    drawRegionMap.abortOngoingDrawSketch?.();
    drawRegionMap.destroyMap?.();
})
const goBack = () => {
    if (route.query.targetUrl) {
        router.replace(route.query.targetUrl);
        return;
    }
    router.go(-1);
};

const resetPolygon = () => {
    clearDeleteSelectionState();
    ElMessageBox.confirm(
        "确认重置当前地块吗？重置后将恢复为初始状态",
        "重置确认",
        {
            confirmButtonText: "确认重置",
            cancelButtonText: "取消",
            type: "warning",
        }
    )
        .then(() => {
            // 先取消进行中的勾画草图（未完成时线条在 Draw 的 overlay 上，清 source 去不掉）
            drawRegionMap.abortOngoingDrawSketch();
            // 只清空当前可编辑多边形，不影响只读状态图层
            if (drawRegionMap.kmap && drawRegionMap.kmap.polygonLayer && drawRegionMap.kmap.polygonLayer.source) {
                drawRegionMap.kmap.polygonLayer.source.clear();
            }

            // 清空当前 tab 草稿，重置应回到“进入时初始化值”
            const currentTab = varietyTabs.value?.[activeVariety.value];
            const currentKey = draftKeyFromParts(activeRegionType.value, currentTab);
            if (currentKey && regionsDraftByKey.value[currentKey]) {
                delete regionsDraftByKey.value[currentKey];
            }
            if (regionsDraftByIndex.value[activeVariety.value]) {
                delete regionsDraftByIndex.value[activeVariety.value];
            }

            // 当前品类有初始化地块则回显；没有则保持空地图
            const initialGeomArrRaw = (() => {
                const fromItems = getGeomArrFromGeomItems(currentTab);
                if (fromItems.length) return fromItems;
                return isValidGeom(currentTab?.geom) ? [String(currentTab.geom).trim()] : [];
            })();
            const initialGeomArr = getEditableGeomArrForCurrentTab(currentTab, initialGeomArrRaw);
            if (
                !viewOnly.value &&
                activeRegionType.value !== "variety" &&
                isLockedAbnormalTab(currentTab)
            ) {
                drawRegionMap.setStatusRegions([
                    ...getAllVarietyReadonlyRegions(),
                    ...getLockedDiseaseRegions(currentTab),
                ]);
            }
            if (initialGeomArr.length > 0) {
                drawRegionMap.setAreaGeometry(
                    initialGeomArr,
                    false,
                    undefined,
                    undefined,
                    getAbnormalGrowthOverlayMeta
                );
                regionGeom.value =
                    initialGeomArr.length > 1 ? JSON.stringify(initialGeomArr) : initialGeomArr[0];
            } else {
                regionGeom.value = "";
                drawRegionMap.fitAllRegions?.();
            }
            ElMessage.success("地块已重置");
        })
        .catch(() => {
            // 用户取消重置，不做任何操作
        });
};

const submitRegions = async () => {
    if (submitting.value) return;
    const regionList = buildRegionListForSubmit();
    const problemZoneList = buildProblemZoneListForSubmit();
    if (regionList.length === 0 && problemZoneList.length === 0) {
        ElMessage.warning("请先勾画地块后再确认");
        return false;
    }
    submitting.value = true;
    try {
        const params = {
            subjectId: route.query.subjectId,
            regionList,
            problemZoneList,
        };
        const res = await VE_API.basic_farm.ediRegionZone(params);
        if (res?.code === 0) {
            if (selectedDrawTypeMeta.value.type === 'ABNORMAL') {
                let problemZoneId = null;
                if (params.problemZoneList.length) {
                    res.data[0].problemZoneList.forEach(element => {
                        if (element.code === selectedDrawTypeMeta.value.type) {
                            element.children.forEach(item => {
                                if (item.problemZoneTypeName === selectedDrawTypeMeta.value.category.problemZoneTypeName) {
                                    problemZoneId = item.id;
                                }
                            });
                        }
                    });
                }
                VE_API.basic_farm.saveProblemZoneImage({
                    problemZoneId,
                    imagePathList: selectedDrawTypeMeta.value.images,
                })
            }
            return true;
        }
        ElMessage.error(res?.msg || "保存失败");
        return false;
    } catch (e) {
        ElMessage.error("保存失败");
        return false;
    } finally {
        submitting.value = false;
    }
};

const submitCurrentTabGeometryChange = async (geomWktOrArr) => {
    const tab = varietyTabs.value?.[activeVariety.value];
    if (!tab) return false;
    const geometryArr = Array.isArray(geomWktOrArr)
        ? geomWktOrArr
        : isValidGeom(geomWktOrArr)
            ? [String(geomWktOrArr).trim()]
            : [];
    const normalizedGeom = mergePolygonWktsForApi(geometryArr);
    const params = {
        subjectId: route.query.subjectId,
        regionList: [],
        problemZoneList: [],
    };

    if (activeRegionType.value === "variety") {
        params.regionList = [
            {
                regionId: tab.regionId,
                typeId: tab.typeId,
                regionName: tab.regionName,
                geom: normalizedGeom,
            },
        ];
    } else {
        const group = findProblemZoneGroupByDrawType(activeRegionType.value);
        if (!group) return false;
        const geomItems = isLockedAbnormalTab(tab)
            ? buildDiseaseGeomItemsForSubmit(tab, geometryArr)
            : buildGeomItemsFromGeometryArr(tab, geometryArr);
        params.problemZoneList = [
            {
                name: group.name,
                code: group.code,
                children: [
                    {
                        farmSubjectId: route.query.subjectId,
                        problemZoneTypeId: tab.problemZoneTypeId ?? tab.typeId ?? "",
                        problemZoneTypeName: tab.problemZoneTypeName ?? tab.regionName ?? "",
                        parentName: group.name ?? "",
                        parentCode: group.code ?? "",
                        geomItems,
                    },
                ],
            },
        ];
    }

    const res = await VE_API.basic_farm.ediRegionZone(params);
    return res?.code === 0;
};

/** 以弹窗 confirm 传入的 drawMeta（大类 type + 小类 category + remark）为准写入草稿并提交 */
const confirmArea = async (drawMeta) => {
    const meta =
        drawMeta && drawMeta.type != null
            ? drawMeta
            : selectedDrawTypeMeta.value;
    if (!meta?.type || meta.category == null) {
        ElMessage.warning("请先在弹窗中选择勾画类型与类别");
        return;
    }
    const polygonData = drawRegionMap.getAreaGeometry?.();
    const geometryArr = polygonData?.geometryArr;
    if (!Array.isArray(geometryArr) || geometryArr.length === 0) {
        ElMessage.warning("请先勾画地块后再确认");
        return;
    }
    const normalizedGeomArr = flattenGeomWktListForMap(geometryArr);
    if (!Array.isArray(normalizedGeomArr) || normalizedGeomArr.length === 0) {
        ElMessage.warning("地块几何无效，请重新勾画");
        return;
    }
    const key = draftKeyFromParts(meta.type, meta.category);
    if (!key) {
        ElMessage.warning("无法识别勾画类别，请重新选择");
        return;
    }
    const geom = mergePolygonWktsForApi(normalizedGeomArr);
    const currentTab = varietyTabs.value?.[activeVariety.value];
    const nextDraft = {
        geomArr: normalizedGeomArr,
        geom,
        remark: meta.remark != null ? String(meta.remark) : "",
    };
    if (meta.type !== "variety") {
        nextDraft.geomItems = isLockedAbnormalTab(currentTab)
            ? buildDiseaseGeomItemsForSubmit(currentTab, normalizedGeomArr, meta.remark)
            : buildGeomItemsFromGeometryArr(currentTab, normalizedGeomArr, meta.remark);
    }
    regionsDraftByKey.value[key] = nextDraft;
    const tabList = getTabsForMajorType(meta.type);
    const idx = findTabIndexForCategory(tabList, meta.category);
    if (activeRegionType.value === meta.type && idx >= 0) {
        regionsDraftByIndex.value[idx] = { geomArr: normalizedGeomArr, geom };
    }

    const ok = await submitRegions();
    const rid = meta.category?.regionId;
    if (rid != null && rid !== "") {
        try {
            await VE_API.basic_farm.updateLastViewTime({ regionId: rid });
        } catch (_) {
            /* 非品种区可能无 regionId，忽略 */
        }
    }
    if (!ok) return;

    // 保存成功后：不跳走，刷新当前页并回显最新数据，并切换为查看态
    try {
        await fetchRegionInfo();
        // 接口已是最新几何与 id，清空草稿避免旧 key/下标回退遮挡 geomItems
        clearAllRegionDrafts();

        // 恢复当前大类下的子类 tab（fetchRegionInfo 默认会填充品种区）
        if (activeRegionType.value === "variety") {
            varietyTabs.value = regionInfo.value?.regionList || [];
        } else {
            const group = (regionTypeTabs.value || []).find(
                (x) => x?.code === activeRegionType.value
            );
            varietyTabs.value = group?.children || [];
        }

        // 更新路由为查看态，确保按钮/头部状态同步
        try {
            router.replace({ query: { ...route.query, type: "viewOnly" } });
        } catch (_) {
            // 路由更新失败不影响回显
        }

        // 重新初始化地图（非编辑/查看模式），确保回显形状正确
        if (drawRegionMap.kmap) {
            drawRegionMap.destroyMap?.();
        }
        drawRegionMap.initMap(point.value, mapContainer.value, false, true, false);
        applyRegionStyles();
        if (varietyTabs.value.length > 0 && varietyTabs.value[activeVariety.value]) {
            handleVarietyClick(varietyTabs.value[activeVariety.value], activeVariety.value);
        }
        drawRegionMap.fitAllRegions?.();
    } catch (_) {
        // 刷新失败不阻断用户继续操作，保持当前页面状态
    }

    if (route.query.showTipPopup) {
        showTipPopup.value = true;
        return;
    }
};

const openConfirmDrawTypePopup = () => {
    const polygonData = drawRegionMap.getAreaGeometry?.();
    const geometryArr = polygonData?.geometryArr;
    if (!Array.isArray(geometryArr) || geometryArr.length === 0) {
        ElMessage.warning("请先勾画地块后再确认");
        return;
    }

    const remark = varietyTabs?.value?.[activeVariety.value]?.geomItems?.[0]?.remark;
    confirmDrawTypePopupRef.value.openPopup({
        regionInfo: regionInfo.value,
        activeRegionType: activeRegionType.value,
        activeVarietyIndex: activeVariety.value,
        remark: activeRegionType.value === 'variety' ? '' : remark,
    });
};

const handleConfirmDrawType = async (payload) => {
    selectedDrawTypeMeta.value = payload;
    await confirmArea(payload);
};

const handleEditRegion = async () => {
    clearDeleteSelectionState();
    // 从查看态切换到可勾画编辑态：移除查看标记（所有大类共用）
    const nextQuery = { ...route.query };
    delete nextQuery.type;
    delete nextQuery.viewOnly;
    clearPendingGeomRenderTimer();
    await router.replace({ query: nextQuery });

    nextTick(() => {
        if (drawRegionMap.kmap) {
            drawRegionMap.abortOngoingDrawSketch?.();
            drawRegionMap.destroyMap();
        }

        // 若当前不在品种区（如环境/异常/休眠），点击“编辑”进入当前问题区的编辑态：
        // - 地图可编辑（仅编辑当前选中的问题区子项）
        // - 只显示「品种区」地块作为底图参考（只读）
        // - 不显示其它问题区地块
        if (activeRegionType.value !== "variety") {
            drawRegionMap.initMap(point.value, mapContainer.value, true, true, true, syncClosedDrawToDraft);
            applyRegionStyles();
            // 清空当前可编辑图层，避免残留
            drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
            const tab = varietyTabs.value?.[activeVariety.value];
            if (isLockedAbnormalTab(tab)) {
                drawRegionMap.setStatusRegions([
                    ...getAllVarietyReadonlyRegions(),
                    ...getLockedDiseaseRegions(tab),
                ]);
            } else {
                renderAllVarietyRegionsReadonlyOnly();
            }

            // 进入编辑时：缩放到当前要编辑的地块
            // 异常锁定小类（2/3）进入编辑态时，禁止从 tab.geom / draftGeom 回填到可编辑层，避免与只读层重叠
            const currentGeomArrRaw = isLockedAbnormalTab(tab)
                ? getGeomArrFromGeomItems(tab)
                : (() => {
                    const currentGeomStr = tab
                        ? (getDraftGeomForTab(activeRegionType.value, tab, activeVariety.value) || tab.geom)
                        : "";
                    return isValidGeom(currentGeomStr)
                        ? [String(currentGeomStr).trim()]
                        : getGeomArrFromGeomItems(tab);
                })();
            const currentGeomArr = getEditableGeomArrForCurrentTab(tab, currentGeomArrRaw);
            regionGeom.value =
                currentGeomArr.length > 1 ? JSON.stringify(currentGeomArr) : currentGeomArr[0] || "";
            if (currentGeomArr.length > 0) {
                drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
                drawRegionMap.setAreaGeometry(
                    currentGeomArr,
                    true,
                    undefined,
                    undefined,
                    getAbnormalGrowthOverlayMeta
                );
                purgeLockedFeaturesFromEditableLayer(tab);
            } else {
                // 仍自适应到品种区底图
                drawRegionMap.fitAllRegions?.();
            }
            return;
        }

        drawRegionMap.initMap(point.value, mapContainer.value, true, true, true, syncClosedDrawToDraft);
        applyRegionStyles();

        // 切到编辑态后：统一走一遍当前 tab 的点击逻辑，确保所有有地块的品种都能显示
        if (varietyTabs.value.length && varietyTabs.value[activeVariety.value]) {
            // 进入编辑时：让当前品种地块显示且缩放到当前编辑地块
            handleVarietyClick(varietyTabs.value[activeVariety.value], activeVariety.value);
            const tab = varietyTabs.value[activeVariety.value];
            const draftGeom = getDraftGeomForTab(activeRegionType.value, tab, activeVariety.value);
            const rawGeomArr =
                isValidGeom(draftGeom)
                    ? [String(draftGeom).trim()]
                    : (() => {
                        const fromItems = getGeomArrFromGeomItems(tab);
                        if (fromItems.length) return fromItems;
                        return isValidGeom(tab?.geom) ? [String(tab.geom).trim()] : [];
                    })();
            const geomArr = flattenGeomWktListForMap(rawGeomArr);
            drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
            if (geomArr.length > 0) {
                drawRegionMap.setAreaGeometry(
                    geomArr,
                    true,
                    undefined,
                    undefined,
                    getAbnormalGrowthOverlayMeta
                );
            }
        } else {
            renderReadonlyVarietyRegions(activeVariety.value);
            const fallbackGeom = regionGeom.value;
            if (isValidGeom(fallbackGeom)) {
                drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
                drawRegionMap.setAreaGeometry(
                    [fallbackGeom],
                    true,
                    undefined,
                    undefined,
                    getAbnormalGrowthOverlayMeta
                );
            }
        }
        // 编辑态下：保持缩放在当前要编辑地块，不再强制 fitAllRegions 覆盖
    });
};

const showTipPopup = ref(false);
const handleTipConfirm = () => {
    const query = {
        hideInteraction: "true",
    };
    if (route.query.addVarietyCount) {
        query.addVarietyCount = String(route.query.addVarietyCount);
    }
    router.push({ path: "/growth_report", query });
}
</script>

<style lang="scss" scoped>
.edit-map {
    width: 100%;
    height: 100vh;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    box-sizing: border-box;

    &> :first-child {
        flex-shrink: 0;
    }

    .region-type-tabs {
        flex-shrink: 0;
        display: flex;
        align-items: center;
        background: #f4f4f4;
        margin: 10px 10px 0;
        padding: 3px;
        border-radius: 4px;
        box-sizing: border-box;

        .region-type-tab {
            flex: 1;
            text-align: center;
            padding: 5px 0;
            color: #767676;
        }

        .region-type-tab--active {
            background: #ffffff;
            border-radius: 4px;
            color: #0D0D0D;
        }
    }

    .variety-tabs {
        flex-shrink: 0;
        display: flex;
        align-items: center;
        gap: 8px;
        padding: 10px 12px 0;
        overflow-x: auto;
        overflow-y: hidden;
        flex-wrap: nowrap;
        -webkit-overflow-scrolling: touch;

        .variety-tab {
            padding: 4px 12px;
            border-radius: 2px;
            color: #575757;
            background: #F4F4F4;
            border: 1px solid transparent;
            white-space: nowrap;
        }

        .variety-tab--active {
            background: rgba(33, 153, 248, 0.1);
            color: #2199F8;
            border: 1px solid #2199F8;
        }
    }

    .edit-map-content {
        width: 100%;
        margin-top: 10px;
        flex: 1;
        min-height: 0;
        position: relative;
        box-sizing: border-box;
        /* 底部「重置 / 确认」等为 position:fixed，占高约 68px，地图区域需预留避免被盖住 */
        padding-bottom: 68px;

        .edit-map-tip {
            position: absolute;
            top: 23px;
            left: calc(50% - 256px / 2);
            z-index: 1;
            font-size: 12px;
            color: #fff;
            padding: 9px 20px;
            background: rgba(0, 0, 0, 0.5);
            border-radius: 20px;
        }

        .map-container {
            width: 100%;
            height: 100%;
        }

        .edit-map-footer {
            position: absolute;
            bottom: 85px;
            left: 12px;
            width: calc(100% - 24px);
            display: flex;
            flex-direction: column;
            align-items: flex-end;

            .footer-back {
                padding: 4px 5px 7px;
                background: #fff;
                border-radius: 8px;
                margin-bottom: 12px;

                .back-icon {
                    width: 23px;
                    height: 23px;
                }
            }

            .edit-map-footer-btn {
                display: flex;
                justify-content: space-between;
                align-items: center;
                width: 100%;
                position: fixed;
                bottom: 0;
                left: 0;
                background: #fff;
                padding: 10px 12px 20px 12px;
                box-sizing: border-box;

                &.confirm-btn-box {
                    justify-content: center;
                }

                div {
                    width: 100px;
                    text-align: center;
                    color: #666666;
                    font-size: 14px;
                    padding: 8px 0;
                    border-radius: 25px;
                    border: 0.5px solid rgba(153, 153, 153, 0.5);
                }

                .btn-confirm {
                    background: #2199F8;
                    color: #fff;
                    border: 1px solid #2199F8;
                }
            }
        }
    }
}
</style>
