import {
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
  type ComponentProps,
  type CSSProperties
} from "react";
import { AnimatePresence, motion, useReducedMotion } from "motion/react";
import { CalendarClock } from "lucide-react";
import {
  AgentCommandPanel,
  AgentPersona,
  toTrustedMapAction,
  type FrontendActionRequest,
  type UIEnvelopePayload,
  type AgentUiResult
} from "@/features/agent";
import {
  MapErrorNotice,
  MapLoadingNotice,
  MapScaleLine,
  MapSourceStatusNotice,
  MapToolbar,
  MapZoom,
  showMapNotice,
  type MapToolbarItem,
  type MapSourceStatus
} from "@/features/map/core";
import { env } from "@/shared/config/env";
import { AgentTaskTicker } from "./components/agent-task-ticker";
import { MapDevPanel } from "./components/map-dev-panel";
import {
  MobileWorkbenchSheet,
  type MobileWorkbenchSheetSnap
} from "./components/mobile-workbench-sheet";
import { FeaturePopover } from "./components/feature-popover";
import { ScheduledConditionFeed } from "./components/scheduled-condition-feed";
import { WorkbenchAgentPanels } from "./components/workbench-agent-panels";
import {
  ToolbarPanel,
  type ExportViewPreset,
  type ToolbarPanelProps,
  type ToolbarToolId
} from "./components/toolbar-panel";
import { WorkbenchTopBar } from "./components/workbench-top-bar";
import { WORKBENCH_SCENARIOS, WORKBENCH_USER } from "./data/workbench-session";
import { useWorkbenchAgent } from "./hooks/use-workbench-agent";
import { useWorkbenchDrawing, type WorkbenchDrawMode } from "./hooks/use-workbench-drawing";
import { useWorkbenchMap } from "./hooks/use-workbench-map";
import { useWorkbenchMapController } from "./hooks/use-workbench-map-controller";
import { useWorkbenchRuntimeData } from "./hooks/use-workbench-runtime-data";
import { toMapFeatureReference } from "./hooks/use-map-interactions";
import {
  useWorkbenchMeasurement,
  type WorkbenchMeasureMode,
  type WorkbenchMeasureUnit
} from "./hooks/use-workbench-measurement";
import {
  WORKBENCH_LAYOUT,
  getWorkbenchBasemapTone,
  getWorkbenchLayoutCssVariables
} from "./layout/workbench-layout";
import { getResponsiveWorkbenchPadding } from "./map/camera";
import { exportMapViewImage } from "./map/export-view";
import { parseScadaAnalysisItems } from "./map/scada-analysis";
import {
  BASE_LAYER_OPTIONS,
  INITIAL_LAYER_VISIBILITY,
  MAP_LEGEND_ITEMS,
  WORKBENCH_LAYER_GROUPS,
  applyBaseLayerVisibility,
  createLayerControlItems,
  getWorkbenchLayerIds
} from "./map/map-control-config";
import { waterNetworkToolbarItems } from "./map/toolbar-config";
import type {
  DetailFeature,
  ScheduledConditionItem,
  ScheduledConditionRecord,
  WorkbenchAlert
} from "./types";
import {
  createScheduledConditionAlerts,
  getScheduledConditionIdFromAlertId
} from "./utils/scheduled-condition-alerts";
import { createAlertQueueConversationPrompt } from "./utils/scheduled-condition-prompts";

const WORKBENCH_LAYOUT_CSS_VARIABLES = getWorkbenchLayoutCssVariables();

export function MapWorkbenchPage() {
  const hasMapboxToken = Boolean(env.TJWATER_MAPBOX_ACCESS_TOKEN);
  const devPanelEnabled = env.TJWATER_ENABLE_DEV_PANEL;
  const mapContainerRef = useRef<HTMLDivElement | null>(null);
  const [detailFeature, setDetailFeature] = useState<DetailFeature | null>(null);
  const [devPanelOpen, setDevPanelOpen] = useState(false);
  const [impactVisible, setImpactVisible] = useState(false);
  const [isLargeScreen, setIsLargeScreen] = useState(false);
  const [viewportWidth, setViewportWidth] = useState<number>(WORKBENCH_LAYOUT.desktopMinWidth);
  const [agentPanelWidth, setAgentPanelWidth] = useState<number>(
    WORKBENCH_LAYOUT.desktop.agentWidth
  );
  const [activeToolId, setActiveToolId] = useState<ToolbarToolId | null>(null);
  const [conditionFeedVisible, setConditionFeedVisible] = useState(false);
  const [conditionFeedMounted, setConditionFeedMounted] = useState(true);
  const [conditionFeedExpanded, setConditionFeedExpanded] = useState(false);
  const [mobileSheet, setMobileSheet] = useState<"agent" | "condition" | null>(null);
  const [mobileSheetSnap, setMobileSheetSnap] = useState<MobileWorkbenchSheetSnap>("half");
  const [agentCollapsedForCondition, setAgentCollapsedForCondition] = useState(false);
  const prefersReducedMotion = useReducedMotion();
  const [taskTickerVisible, setTaskTickerVisible] = useState(true);
  const [selectedConditionId, setSelectedConditionId] = useState<string | null>(null);
  const [conditionFocusRequest, setConditionFocusRequest] = useState<{
    conditionId: string;
    requestId: number;
  } | null>(null);
  const [activeBaseLayerId, setActiveBaseLayerId] = useState(
    hasMapboxToken ? "mapbox-light" : "none"
  );
  const basemapTone = getWorkbenchBasemapTone(activeBaseLayerId);
  const [activeScenarioId, setActiveScenarioId] = useState(WORKBENCH_SCENARIOS[0]?.id ?? "");
  const [activeMeasureModeId, setActiveMeasureModeId] = useState<WorkbenchMeasureMode>("distance");
  const [activeMeasureUnitId, setActiveMeasureUnitId] = useState<WorkbenchMeasureUnit>("km");
  const [activeDrawToolId, setActiveDrawToolId] = useState<WorkbenchDrawMode | null>(null);
  const [layerVisibility, setLayerVisibility] =
    useState<Record<string, boolean>>(INITIAL_LAYER_VISIBILITY);
  const [agentUiResults, setAgentUiResults] = useState<AgentUiResult[]>([]);
  const { headerDataTime, scheduledConditions, scheduledConditionsLoading } =
    useWorkbenchRuntimeData();
  const baseLayerOptions = useMemo(
    () =>
      BASE_LAYER_OPTIONS.map((option) => ({
        ...option,
        disabled: option.id !== "none" && !hasMapboxToken
      })),
    [hasMapboxToken]
  );

  const handleSelectFeature = useCallback((feature: DetailFeature) => {
    setDetailFeature(feature);
  }, []);

  useEffect(() => {
    const mediaQuery = window.matchMedia("(min-width: 1024px)");
    const handleChange = () => {
      setIsLargeScreen(mediaQuery.matches);
      setViewportWidth(window.innerWidth);
      if (mediaQuery.matches) {
        setMobileSheet(null);
      }
    };

    handleChange();
    setConditionFeedVisible(window.innerWidth >= 1280);
    mediaQuery.addEventListener("change", handleChange);
    window.addEventListener("resize", handleChange);

    return () => {
      mediaQuery.removeEventListener("change", handleChange);
      window.removeEventListener("resize", handleChange);
    };
  }, []);

  const shouldShowConditionFeed = conditionFeedVisible && !activeToolId;

  useEffect(() => {
    if (shouldShowConditionFeed) {
      setConditionFeedMounted(true);
      return;
    }

    const timeoutId = window.setTimeout(() => {
      setConditionFeedMounted(false);
    }, 170);

    return () => window.clearTimeout(timeoutId);
  }, [shouldShowConditionFeed]);

  const agent = useWorkbenchAgent({
    onUiEnvelope: handleAgentUiEnvelope,
    onFrontendAction: handleFrontendAction
  });
  function openAgentPanelForViewport() {
    if (isLargeScreen) {
      if (conditionFeedExpanded && viewportWidth < 1440) {
        setConditionFeedExpanded(false);
        setAgentCollapsedForCondition(false);
      }
      agent.expandPanel();
      return;
    }

    setMobileSheet("agent");
    setMobileSheetSnap("half");
  }

  const closeMobileSheet = useCallback(() => {
    setMobileSheet(null);
  }, []);

  function handleConditionExpandedChange(nextExpanded: boolean) {
    if (nextExpanded && isLargeScreen && viewportWidth < 1440) {
      setAgentCollapsedForCondition(agent.panelOpen);
      agent.collapsePanel();
    } else if (!nextExpanded && agentCollapsedForCondition) {
      setAgentCollapsedForCondition(false);
      agent.expandPanel();
    }
    setConditionFeedExpanded(nextExpanded);
  }

  useEffect(() => {
    if (!isLargeScreen || shouldShowConditionFeed || !conditionFeedExpanded) {
      return;
    }

    setConditionFeedExpanded(false);
    if (agentCollapsedForCondition) {
      setAgentCollapsedForCondition(false);
      agent.expandPanel();
    }
  }, [
    agent,
    agentCollapsedForCondition,
    conditionFeedExpanded,
    isLargeScreen,
    shouldShowConditionFeed
  ]);

  function toggleConditionFeedForViewport() {
    setActiveToolId(null);
    if (isLargeScreen) {
      setConditionFeedVisible((current) => !current);
      return;
    }

    if (mobileSheet === "condition") {
      closeMobileSheet();
      return;
    }

    setConditionFeedExpanded(false);
    setMobileSheetSnap("half");
    setMobileSheet("condition");
  }

  const leftPanelOpen = isLargeScreen && agent.panelOpen;
  const rightPanelOpen = isLargeScreen && (devPanelOpen || shouldShowConditionFeed);
  const rightPanelExpanded =
    isLargeScreen && shouldShowConditionFeed && conditionFeedExpanded && !devPanelOpen;

  const { mapRef, mapReady, mapError, sourceStatuses, fitNetworkBounds } = useWorkbenchMap({
    containerRef: mapContainerRef,
    impactVisible,
    onSelectFeature: handleSelectFeature,
    selectedFeature: detailFeature
  });
  const { controller: mapController, state: mapControllerState } = useWorkbenchMapController({
    mapRef,
    mapReady,
    leftPanelOpen,
    rightPanelOpen,
    conditionPanelExpanded: rightPanelExpanded,
    agentPanelWidth
  });

  const activeAgentUiResults = useMemo(
    () => agentUiResults.filter((result) => result.sessionId === agent.sessionId),
    [agent.sessionId, agentUiResults]
  );
  const conditionAlerts = useMemo(
    () => createScheduledConditionAlerts(scheduledConditions),
    [scheduledConditions]
  );
  const runningTickerConditions = useMemo(
    () =>
      scheduledConditions.filter(
        (condition): condition is ScheduledConditionRecord =>
          condition.kind === "condition" && condition.status === "running"
      ),
    [scheduledConditions]
  );
  const workbenchAlerts = conditionAlerts;

  const drawing = useWorkbenchDrawing({
    mapRef,
    mapReady,
    activeMode: activeDrawToolId,
    onModeChange: setActiveDrawToolId
  });

  const measurement = useWorkbenchMeasurement({
    mapRef,
    mapReady,
    mode: activeMeasureModeId,
    unit: activeMeasureUnitId
  });
  const taskTickerAvailable = runningTickerConditions.length > 0;
  const shouldShowTaskTicker =
    mobileSheet === null && !conditionFeedExpanded && taskTickerVisible && taskTickerAvailable;
  const taskTickerEnterState = prefersReducedMotion
    ? {
        opacity: 1,
        scale: 1,
        y: 0
      }
    : {
        opacity: 1,
        scale: 1,
        y: 0,
        transition: {
          type: "spring" as const,
          stiffness: 420,
          damping: 30,
          mass: 0.75
        }
      };
  const taskTickerExitState = prefersReducedMotion
    ? {
        opacity: 0,
        scale: 1,
        y: 0,
        transition: { duration: 0 }
      }
    : {
        opacity: 0,
        scale: 0.96,
        y: -8,
        transition: {
          duration: 0.18,
          ease: [0.5, 0, 0.2, 1] as const
        }
      };

  useEffect(() => {
    if (!mapReady || !mapRef.current) {
      return;
    }

    applyBaseLayerVisibility(mapRef.current, activeBaseLayerId);
  }, [activeBaseLayerId, mapReady, mapRef]);

  const toggleToolbarTool = useCallback((toolId: ToolbarToolId) => {
    setActiveToolId((current) => {
      return current === toolId ? null : toolId;
    });
  }, []);

  const handleConditionFocusRequestHandled = useCallback((requestId: number) => {
    setConditionFocusRequest((current) => (current?.requestId === requestId ? null : current));
  }, []);

  const toolbarItems = useMemo<MapToolbarItem[]>(
    () =>
      waterNetworkToolbarItems.map((item) => ({
        ...item,
        active: activeToolId === item.id,
        disabled: !mapReady,
        onClick: () => toggleToolbarTool(item.id as ToolbarToolId)
      })),
    [activeToolId, mapReady, toggleToolbarTool]
  );

  const layerControlItems = useMemo(
    () => createLayerControlItems(layerVisibility),
    [layerVisibility]
  );
  function handleToggleLayer(layerControlId: string, visible: boolean) {
    const map = mapRef.current;

    setLayerVisibility((current) => ({ ...current, [layerControlId]: visible }));
    if (layerControlId === "simulation") {
      setImpactVisible(visible);
    }

    if (!map || !mapReady) {
      return;
    }

    getWorkbenchLayerIds(map, layerControlId).forEach((layerId) => {
      if (map.getLayer(layerId)) {
        map.setLayoutProperty(layerId, "visibility", visible ? "visible" : "none");
      }
    });
  }

  async function handleExportView(preset: ExportViewPreset) {
    const map = mapRef.current;
    if (!map || !mapReady) {
      showMapNotice({ tone: "warning", message: "地图尚未就绪，无法导出视图。" });
      return;
    }

    const targetLongEdge = getExportTargetLongEdge(preset);
    const exportLabel = getExportPresetLabel(preset);

    showMapNotice({
      id: "map-view-export",
      tone: "loading",
      title: "正在导出",
      message: `正在生成${exportLabel}地图截图...`,
      duration: Infinity
    });

    try {
      const result = await exportMapViewImage(map, {
        scale: preset === "current" ? 1 : undefined,
        targetLongEdge,
        selectedFeature: toMapFeatureReference(detailFeature)
      });
      showMapNotice({
        id: "map-view-export",
        tone: "success",
        message: `已导出 ${result.width} × ${result.height} PNG。`
      });
    } catch {
      showMapNotice({
        id: "map-view-export",
        tone: "error",
        title: "导出失败",
        message: "当前底图或瓦片可能限制了画布导出。"
      });
    }
  }

  function handleRefreshTiles() {
    const map = mapRef.current;
    if (!map || !mapReady) {
      showMapNotice({ tone: "warning", message: "地图尚未就绪，无法刷新瓦片。" });
      return;
    }

    map.triggerRepaint();
    showMapNotice({ tone: "success", message: "已请求地图重新渲染，业务瓦片将在视图变化时刷新。" });
  }

  function handleShowDataStatus() {
    if (sourceStatuses.length === 0) {
      showMapNotice({ tone: "info", message: "数据源状态正在初始化。" });
      return;
    }

    showMapNotice({
      tone: sourceStatuses.some((sourceStatus) => sourceStatus.status === "offline")
        ? "warning"
        : "info",
      title: "数据状态",
      message: sourceStatuses
        .map((sourceStatus) => `${sourceStatus.sourceName}：${sourceStatus.status}`)
        .join(" · "),
      duration: 5000
    });
  }

  function handleShowShortcuts() {
    showMapNotice({
      tone: "info",
      title: "快捷键",
      message: "双击完成线/面绘制；圆形标注先点圆心，再点半径；Esc 可作为后续快捷键扩展。",
      duration: 6000
    });
  }

  function handleSelectScenario(scenarioId: string) {
    const scenario = WORKBENCH_SCENARIOS.find((item) => item.id === scenarioId);
    setActiveScenarioId(scenarioId);
    showMapNotice({
      tone: "success",
      title: "方案已切换",
      message: `当前方案：${scenario?.name ?? scenarioId}。地图模拟结果暂未自动切换。`
    });
  }

  function handlePreviewScenario() {
    setImpactVisible(true);
    setLayerVisibility((current) => ({ ...current, simulation: true }));

    if (mapRef.current && mapReady) {
      WORKBENCH_LAYER_GROUPS.simulation.forEach((layerId) => {
        if (mapRef.current?.getLayer(layerId)) {
          mapRef.current.setLayoutProperty(layerId, "visibility", "visible");
        }
      });
    }

    showMapNotice({
      tone: "info",
      title: "预览影响范围",
      message: "已打开模拟结果图层，可在右侧图层面板继续调整显示。"
    });
  }

  function handleCompareScenario() {
    showMapNotice({
      tone: "info",
      title: "方案比较",
      message: "候选方案比较将汇总影响范围、阀门操作与保供风险。"
    });
  }

  function handleExportScenarioReport() {
    showMapNotice({
      tone: "success",
      title: "场景报告",
      message: "已生成当前场景报告任务，可继续导出地图截图或配置。"
    });
  }

  async function handleAnalyzeAlertsWithAgent() {
    if (workbenchAlerts.length === 0) {
      showMapNotice({
        tone: "info",
        title: "当前无待复核工况",
        message: "当前没有需要汇总的工况提醒。"
      });
      return;
    }

    if (agent.streaming) {
      showMapNotice({ tone: "warning", message: "Agent 正在处理上一条指令。" });
      return;
    }

    openAgentPanelForViewport();

    try {
      await agent.submitPrompt(
        createAlertQueueConversationPrompt({
          alerts: workbenchAlerts,
          conditions: scheduledConditions
        })
      );

      showMapNotice({
        tone: "success",
        title: "已发起工况汇总",
        message: "已将待复核工况发送到 Agent。"
      });
    } catch (error) {
      showMapNotice({
        tone: "error",
        title: "工况汇总发起失败",
        message: error instanceof Error ? error.message : "无法将待复核工况发送到 Agent。"
      });
    }
  }

  function handleSelectAlert(alert: WorkbenchAlert) {
    const conditionId = getScheduledConditionIdFromAlertId(alert.id);
    if (conditionId) {
      const condition = scheduledConditions.find((item) => item.id === conditionId);
      if (!condition) {
        showMapNotice({
          tone: "warning",
          title: "工况任务未找到",
          message: `未找到提醒关联的工况任务：${conditionId}。`
        });
        return;
      }

      setConditionFeedVisible(true);
      setActiveToolId(null);
      if (!isLargeScreen) {
        setMobileSheet("condition");
        setMobileSheetSnap("half");
      }
      setConditionFocusRequest((current) => ({
        conditionId,
        requestId: (current?.requestId ?? 0) + 1
      }));
      return;
    }

    showMapNotice({
      tone: "warning",
      title: alert.title,
      message: alert.description
    });
  }

  async function handleAgentUiEnvelope(payload: UIEnvelopePayload, sessionId: string) {
    const { envelope } = payload;

    if (envelope.kind === "map_action") {
      await handleAgentMapAction(
        envelope.action,
        envelope.params,
        sessionId,
        envelope.fallbackText
      );
      return;
    }

    setAgentUiResults((current) => [
      ...current.slice(-5),
      {
        id: payload.envelope_id || `agent-ui-${Date.now().toString(36)}`,
        sessionId,
        createdAt: payload.created_at,
        envelope
      }
    ]);

    showMapNotice({
      tone: "info",
      title: envelope.kind === "chart" ? "Agent 图表已渲染" : "Agent 面板已渲染",
      message:
        envelope.fallbackText ??
        (envelope.kind === "chart"
          ? "已在 Agent 面板显示可信图表。"
          : "已在 Agent 面板显示可信组件。")
    });
  }

  async function handleFrontendAction(request: FrontendActionRequest, signal: AbortSignal) {
    if (request.name === "render_scada_analysis") {
      const items = parseScadaAnalysisItems(request.params.items);
      if (!items) throw new Error("INVALID_SCADA_ANALYSIS");
      const result = await mapController.renderScadaAnalysis(items, signal);
      const counts = result.level_counts;
      showMapNotice({
        tone: "success",
        title: "Agent SCADA 分析已渲染",
        message: `已渲染 ${result.rendered_ids.length} 个，高 ${counts.high}、中 ${counts.medium}、低 ${counts.low}${result.missing_ids.length ? `，缺失 ${result.missing_ids.length} 个` : ""}。`
      });
      return result;
    }
    if (request.name === "clear_scada_analysis") {
      const result = mapController.clearScadaAnalysis();
      showMapNotice({
        tone: "info",
        title: "Agent SCADA 分析已清除",
        message: "地图已移除当前会话的 SCADA 分析结果。"
      });
      return result;
    }
    throw new Error("UNSUPPORTED_FRONTEND_ACTION");
  }

  async function handleStartNewAgentSession() {
    mapController.clearScadaAnalysis();
    await agent.startNewSession();
  }

  async function handleLoadAgentHistorySession(sessionId: string) {
    if (sessionId !== agent.sessionId) {
      mapController.clearScadaAnalysis();
    }
    await agent.loadHistorySession(sessionId);
  }

  async function handleDeleteAgentHistorySession(sessionId: string) {
    const clearsActiveAnalysis = sessionId === agent.sessionId;
    const deleted = await agent.deleteHistorySession(sessionId);
    if (deleted && clearsActiveAnalysis) {
      mapController.clearScadaAnalysis();
    }
  }

  async function handleAgentMapAction(
    action: string,
    params: unknown,
    sessionId: string,
    fallbackText?: string
  ) {
    const trustedAction = toTrustedMapAction(action, params, fallbackText);
    if (!trustedAction) {
      showMapNotice({
        tone: "warning",
        title: "地图动作已降级",
        message: fallbackText ?? "Agent 地图动作参数未通过前端校验。"
      });
      return;
    }

    if (trustedAction.type === "zoom_to_map") {
      const map = mapRef.current;
      if (!map || !mapReady) {
        showMapNotice({ tone: "warning", message: "地图尚未就绪，无法执行 Agent 缩放动作。" });
        return;
      }

      map.easeTo({
        center: trustedAction.center,
        zoom: trustedAction.zoom ?? Math.max(map.getZoom(), 14),
        padding: getResponsiveWorkbenchPadding(
          map,
          leftPanelOpen,
          rightPanelOpen,
          rightPanelExpanded,
          agentPanelWidth
        ),
        duration: trustedAction.durationMs ?? 500
      });
      showMapNotice({
        tone: "info",
        title: "Agent 地图定位",
        message: trustedAction.fallbackText ?? "已根据 Agent 建议缩放到目标位置。"
      });
      return;
    }

    if (trustedAction.type === "locate_features") {
      fitNetworkBounds();
      showMapNotice({
        tone: "info",
        title: "Agent 资产定位",
        message:
          trustedAction.fallbackText ??
          (trustedAction.featureIds.length > 0
            ? `已接收 ${trustedAction.featureIds.length} 个目标资产，当前先回到全网视图。`
            : "已根据 Agent 建议回到全网视图。")
      });
      return;
    }

    if (trustedAction.type === "apply_layer_style") {
      if (trustedAction.layerGroupId && typeof trustedAction.visible === "boolean") {
        handleToggleLayer(trustedAction.layerGroupId, trustedAction.visible);
      }

      showMapNotice({
        tone: "info",
        title: "Agent 图层样式",
        message: trustedAction.fallbackText ?? "已接收 Agent 图层样式建议，当前仅执行受控图层显隐。"
      });
      return;
    }

    try {
      await agent.resolveRenderRef(trustedAction.renderRef, sessionId);
      showMapNotice({
        tone: "info",
        title: "Agent 节点渲染",
        message: trustedAction.fallbackText ?? "已验证 render_ref，节点分类渲染器将在后续接入。"
      });
    } catch (error) {
      showMapNotice({
        tone: "error",
        title: "render_ref 解析失败",
        message: error instanceof Error ? error.message : "无法读取 Agent 渲染结果。"
      });
    }
  }

  function handleExportConfig() {
    const config = {
      exportedAt: new Date().toISOString(),
      activeBaseLayerId,
      layerVisibility,
      activeToolId,
      activeMeasureModeId,
      activeMeasureUnitId
    };
    const blob = new Blob([JSON.stringify(config, null, 2)], { type: "application/json" });
    const url = URL.createObjectURL(blob);
    const link = document.createElement("a");
    link.href = url;
    link.download = "supply-network-map-config.json";
    document.body.appendChild(link);
    link.click();
    link.remove();
    URL.revokeObjectURL(url);
    showMapNotice({ tone: "success", message: "当前地图配置已导出。" });
  }

  const toolbarPanelProps: ToolbarPanelProps = {
    activeToolId,
    activeMeasureModeId,
    activeMeasureUnitId,
    measuring: measurement.measuring,
    measureResult: measurement.result,
    measureEnabled: mapReady,
    hasMeasurePoints: measurement.hasPoints,
    activeDrawToolId,
    drawingEnabled: mapReady,
    drawingAnnotations: drawing.annotations,
    canUndoDrawing: drawing.canUndo,
    canRedoDrawing: drawing.canRedo,
    canDeleteSelectedDrawing: drawing.canDeleteSelected,
    hasDrawingFeatures: drawing.hasFeatures,
    layerItems: layerControlItems,
    legendItems: MAP_LEGEND_ITEMS,
    baseLayerOptions,
    activeBaseLayerId,
    onSelectMeasureMode: setActiveMeasureModeId,
    onSelectMeasureUnit: setActiveMeasureUnitId,
    onStartMeasure: measurement.start,
    onStopMeasure: measurement.stop,
    onClearMeasure: measurement.clear,
    onCopyMeasure: measurement.copyResult,
    onSelectDrawTool: setActiveDrawToolId,
    onUndoDrawing: drawing.undo,
    onRedoDrawing: drawing.redo,
    onDeleteSelectedDrawing: drawing.deleteSelected,
    onClearDrawing: drawing.clear,
    onExportAnnotations: drawing.exportGeoJSON,
    onSelectBaseLayer: setActiveBaseLayerId,
    onToggleLayer: handleToggleLayer,
    onExportView: handleExportView,
    onRefreshTiles: handleRefreshTiles,
    onShowDataStatus: handleShowDataStatus,
    onShowShortcuts: handleShowShortcuts,
    onExportConfig: handleExportConfig
  };
  const agentPanelProps: Omit<
    ComponentProps<typeof AgentCommandPanel>,
    "collapsing" | "onCollapse"
  > = {
    personaState: agent.personaState,
    sessionTitle: agent.sessionTitle,
    sessionHistory: agent.sessionHistory,
    sessionHistoryLoading: agent.sessionHistoryLoading,
    activeSessionId: agent.sessionId,
    statusLabel: agent.statusLabel,
    connectionStatus: agent.connectionStatus,
    streaming: agent.streaming,
    messages: agent.messages,
    streamRenderState: agent.streamRenderState,
    modelOptions: agent.modelOptions,
    selectedModel: agent.selectedModel,
    approvalMode: agent.approvalMode,
    uiResults: activeAgentUiResults,
    onRefreshHistory: agent.refreshSessionHistory,
    onStartNewSession: handleStartNewAgentSession,
    onLoadHistorySession: handleLoadAgentHistorySession,
    onRenameHistorySession: agent.renameHistorySession,
    onDeleteHistorySession: handleDeleteAgentHistorySession,
    onSelectModel: agent.setSelectedModel,
    onApprovalModeChange: agent.setApprovalMode,
    onSubmitPrompt: agent.submitPrompt,
    onStopPrompt: agent.stopPrompt,
    onReplyPermission: agent.replyPermission,
    onReplyQuestion: agent.replyQuestion,
    onRejectQuestion: agent.rejectQuestion
  };

  return (
    <main
      className="relative h-[100dvh] min-h-[640px] overflow-hidden bg-slate-100 text-slate-900 tabular-nums"
      data-basemap-tone={basemapTone}
      style={
        {
          ...WORKBENCH_LAYOUT_CSS_VARIABLES,
          "--workbench-agent-current-width": `${
            leftPanelOpen ? agentPanelWidth : WORKBENCH_LAYOUT.collapsedAgentWidth
          }px`
        } as CSSProperties
      }
    >
      <div
        ref={mapContainerRef}
        className="map-grid"
        style={{ position: "absolute", inset: 0 }}
        aria-label="供水管网地图"
      />

      <WorkbenchTopBar
        dataTime={headerDataTime}
        modelName="AquaDispatch v1.0"
        scenarios={WORKBENCH_SCENARIOS}
        activeScenarioId={activeScenarioId}
        alerts={workbenchAlerts}
        user={WORKBENCH_USER}
        conditionFeedVisible={isLargeScreen ? shouldShowConditionFeed : mobileSheet === "condition"}
        taskTickerAvailable={taskTickerAvailable}
        taskTickerVisible={taskTickerVisible}
        devPanelEnabled={devPanelEnabled}
        devPanelOpen={devPanelOpen}
        onSelectScenario={handleSelectScenario}
        onSelectAlert={handleSelectAlert}
        onToggleConditionFeed={toggleConditionFeedForViewport}
        onToggleTaskTicker={() => setTaskTickerVisible((current) => !current)}
        onToggleDevPanel={() => setDevPanelOpen((current) => !current)}
        onPreviewScenario={handlePreviewScenario}
        onCompareScenario={handleCompareScenario}
        onExportScenarioReport={handleExportScenarioReport}
        onAnalyzeAlertsWithAgent={handleAnalyzeAlertsWithAgent}
        onShowDataStatus={handleShowDataStatus}
        onRefreshTiles={handleRefreshTiles}
        onShowShortcuts={handleShowShortcuts}
        onExportConfig={handleExportConfig}
      />

      <WorkbenchAgentPanels
        panelProps={agentPanelProps}
        panelOpen={agent.panelOpen}
        panelCollapsing={agent.panelCollapsing}
        conditionExpanded={shouldShowConditionFeed && conditionFeedExpanded}
        personaState={agent.personaState}
        statusLabel={agent.statusLabel}
        viewportWidth={viewportWidth}
        onCollapsePanel={agent.collapsePanel}
        onExpandPanel={agent.expandPanel}
        onWidthCommit={setAgentPanelWidth}
      />

      {!devPanelOpen ? (
        <div className="absolute right-2 top-24 z-20 hidden lg:block">
          <MapToolbar items={toolbarItems} className="hidden lg:block" />
        </div>
      ) : null}

      {conditionFeedMounted && !devPanelOpen ? (
        <div className="absolute right-16 top-24 z-20 hidden lg:block 2xl:[--workbench-condition-width:var(--workbench-condition-width-wide)]">
          <ScheduledConditionFeed
            presentation="desktop-floating"
            conditions={scheduledConditions}
            expanded={conditionFeedExpanded}
            focusRequest={conditionFocusRequest}
            loading={scheduledConditionsLoading}
            visible={shouldShowConditionFeed}
            selectedConditionId={selectedConditionId}
            onExpandedChange={handleConditionExpandedChange}
            onFocusRequestHandled={handleConditionFocusRequestHandled}
            onSelectedConditionChange={setSelectedConditionId}
            onExpandAgent={openAgentPanelForViewport}
            onLoadHistorySession={handleLoadAgentHistorySession}
            onSubmitPrompt={agent.submitPrompt}
          />
        </div>
      ) : null}

      {!devPanelOpen ? (
        <div className="absolute right-16 top-24 z-20 hidden lg:block">
          <ToolbarPanel {...toolbarPanelProps} />
        </div>
      ) : null}

      {devPanelEnabled && devPanelOpen ? (
        <MapDevPanel
          commands={mapController}
          controllerState={mapControllerState}
          detailFeature={detailFeature}
          onClose={() => setDevPanelOpen(false)}
        />
      ) : null}

      {mobileSheet === null ? (
        <div className="absolute bottom-16 left-3 right-3 z-30 lg:hidden">
          <ToolbarPanel
            {...toolbarPanelProps}
            panelWidthClassName="w-full max-h-[52dvh] overflow-y-auto"
          />
        </div>
      ) : null}

      <div className="pointer-events-none absolute bottom-0 right-0 z-30 hidden flex-col items-end gap-2 md:flex">
        <div className="flex items-end gap-2 pr-2">
          <MapZoom mapRef={mapRef} mapReady={mapReady} onHome={fitNetworkBounds} />
        </div>
        <MapScaleLine mapRef={mapRef} mapReady={mapReady} />
      </div>

      <AnimatePresence initial={false}>
        {shouldShowTaskTicker ? (
          <motion.div
            key="agent-task-ticker-shell"
            className="fixed left-1/2 right-auto top-24 z-20 w-[calc(100%-1.5rem)] [translate:-50%_0] md:absolute md:w-[var(--workbench-ticker-width)] 2xl:w-[var(--workbench-ticker-width-wide)]"
            style={{ transformOrigin: "top center" }}
            initial={
              prefersReducedMotion
                ? false
                : {
                    opacity: 0,
                    scale: 0.96,
                    y: -8
                  }
            }
            animate={taskTickerEnterState}
            exit={taskTickerExitState}
          >
            <AgentTaskTicker className="w-full max-w-full" conditions={runningTickerConditions} />
          </motion.div>
        ) : null}
      </AnimatePresence>

      <div className="absolute bottom-3 left-3 right-3 z-30 lg:hidden">
        {mobileSheet === null ? (
          <div className="flex items-center justify-center gap-2">
            <button
              type="button"
              aria-label="打开 Agent 面板"
              title="打开 Agent 面板"
              onClick={openAgentPanelForViewport}
              className="acrylic-control grid h-11 w-11 shrink-0 place-items-center rounded-xl border text-violet-700"
            >
              <AgentPersona className="pointer-events-none h-8 w-8" state={agent.personaState} />
            </button>
            <MapToolbar
              items={toolbarItems}
              orientation="horizontal"
              className="h-11 justify-center"
            />
            <button
              type="button"
              aria-label="打开工况任务"
              title="打开工况任务"
              onClick={toggleConditionFeedForViewport}
              className="acrylic-control grid h-11 w-11 shrink-0 place-items-center rounded-xl border text-blue-700"
            >
              <CalendarClock size={20} aria-hidden="true" />
            </button>
          </div>
        ) : null}
      </div>

      {mobileSheet ? (
        <MobileWorkbenchSheet
          label={mobileSheet === "agent" ? "Agent 工作台抽屉" : "工况任务抽屉"}
          snap={mobileSheetSnap}
          onSnapChange={setMobileSheetSnap}
          onClose={closeMobileSheet}
        >
          {mobileSheet === "agent" ? (
            <AgentCommandPanel
              {...agentPanelProps}
              presentation="mobile-sheet"
              onCollapse={closeMobileSheet}
            />
          ) : (
            <ScheduledConditionFeed
              presentation="mobile-sheet"
              conditions={scheduledConditions}
              expanded={conditionFeedExpanded}
              focusRequest={conditionFocusRequest}
              loading={scheduledConditionsLoading}
              visible
              selectedConditionId={selectedConditionId}
              onExpandedChange={handleConditionExpandedChange}
              onFocusRequestHandled={handleConditionFocusRequestHandled}
              onSelectedConditionChange={setSelectedConditionId}
              onExpandAgent={openAgentPanelForViewport}
              onClose={closeMobileSheet}
              onLoadHistorySession={handleLoadAgentHistorySession}
              onSubmitPrompt={agent.submitPrompt}
            />
          )}
        </MobileWorkbenchSheet>
      ) : null}

      <FeaturePopover feature={detailFeature} onClose={() => setDetailFeature(null)} />

      {!mapReady && !mapError ? (
        <MapLoadingNotice message="正在加载底图样式、管网数据源和交互图层。" />
      ) : null}
      {!hasMapboxToken ? (
        <MapSourceStatusNotice
          sourceName="Mapbox 底图"
          status="degraded"
          message="未检测到 Mapbox token，当前已切换为无底图模式，仅展示业务图层。"
        />
      ) : null}
      {sourceStatuses.filter(isNoticeSourceStatus).map((sourceStatus) => (
        <MapSourceStatusNotice
          key={sourceStatus.id}
          id={`map-source-runtime-${sourceStatus.id}`}
          sourceName={sourceStatus.sourceName}
          status={sourceStatus.status}
          message={sourceStatus.message}
        />
      ))}
      {mapError ? <MapErrorNotice message={mapError} /> : null}
    </main>
  );
}

function isNoticeSourceStatus(sourceStatus: {
  status: string;
}): sourceStatus is { id: string; sourceName: string; status: MapSourceStatus; message: string } {
  return (
    sourceStatus.status === "online" ||
    sourceStatus.status === "degraded" ||
    sourceStatus.status === "offline"
  );
}

function getExportTargetLongEdge(preset: ExportViewPreset) {
  if (preset === "4k") {
    return 3840;
  }

  return undefined;
}

function getExportPresetLabel(preset: ExportViewPreset) {
  if (preset === "4k") {
    return " 4K ";
  }

  return "当前分辨率";
}
