"use client";

import React, { useCallback, useState } from "react";
import {
  Box,
  Button,
  Chip,
  Paper,
  Stack,
  Typography,
  alpha,
  useTheme,
  Collapse,
  IconButton,
} from "@mui/material";
import LocationOnRounded from "@mui/icons-material/LocationOnRounded";
import TimelineRounded from "@mui/icons-material/TimelineRounded";
import SensorsRounded from "@mui/icons-material/SensorsRounded";
import CheckCircleRounded from "@mui/icons-material/CheckCircleRounded";
import KeyboardArrowDownRounded from "@mui/icons-material/KeyboardArrowDownRounded";
import KeyboardArrowUpRounded from "@mui/icons-material/KeyboardArrowUpRounded";

import {
  useChatToolStore,
  type ChatToolAction,
} from "@/store/chatToolStore";
import type { ToolCall } from "./chatMessageSections";
import {
  APPLY_LAYER_STYLE_TOOL,
  describeApplyLayerStyle,
  parseApplyLayerStylePayload,
} from "./toolCallStyleHelpers";

/* ------------------------------------------------------------------ */
/*  Interactive card rendered inside a chat bubble for tool actions    */
/*  (locate nodes/pipes, open history/SCADA panels).                  */
/* ------------------------------------------------------------------ */

type ToolMeta = {
  label: string;
  icon: React.ReactNode;
  actionLabel: string;
  color: string;
};

const LOCATE_TOOL_TO_LAYER: Record<string, string> = {
  locate_features: "",
  locate_junctions: "geo_junctions_mat",
  locate_pipes: "geo_pipes_mat",
  locate_valves: "geo_valves",
  locate_reservoirs: "geo_reservoirs",
  locate_pumps: "geo_pumps",
  locate_tanks: "geo_tanks",
};

const LOCATE_LINE_TOOLS = new Set<string>(["locate_pipes"]);
const LOCATE_ID_PARAM_KEYS = [
  "ids",
  "id",
  "feature_ids",
  "feature_id",
  "node_ids",
  "node_id",
  "junction_ids",
  "junction_id",
  "pipe_ids",
  "pipe_id",
  "valve_ids",
  "valve_id",
  "reservoir_ids",
  "reservoir_id",
  "pump_ids",
  "pump_id",
  "tank_ids",
  "tank_id",
] as const;

const TOOL_META: Record<string, ToolMeta> = {
  locate_features: {
    label: "定位要素",
    icon: <LocationOnRounded sx={{ fontSize: 18 }} />,
    actionLabel: "定位到地图",
    color: "#5470c6",
  },
  locate_junctions: {
    label: "定位节点",
    icon: <LocationOnRounded sx={{ fontSize: 18 }} />,
    actionLabel: "定位到地图",
    color: "#5470c6",
  },
  locate_pipes: {
    label: "定位管道",
    icon: <LocationOnRounded sx={{ fontSize: 18 }} />,
    actionLabel: "定位到地图",
    color: "#91cc75",
  },
  locate_valves: {
    label: "定位阀门",
    icon: <LocationOnRounded sx={{ fontSize: 18 }} />,
    actionLabel: "定位到地图",
    color: "#9a60b4",
  },
  locate_reservoirs: {
    label: "定位水源",
    icon: <LocationOnRounded sx={{ fontSize: 18 }} />,
    actionLabel: "定位到地图",
    color: "#ea7ccc",
  },
  locate_pumps: {
    label: "定位泵站",
    icon: <LocationOnRounded sx={{ fontSize: 18 }} />,
    actionLabel: "定位到地图",
    color: "#fc8452",
  },
  locate_tanks: {
    label: "定位水池",
    icon: <LocationOnRounded sx={{ fontSize: 18 }} />,
    actionLabel: "定位到地图",
    color: "#3ba272",
  },
  zoom_to_map: {
    label: "缩放到坐标",
    icon: <LocationOnRounded sx={{ fontSize: 18 }} />,
    actionLabel: "缩放到地图",
    color: "#0ea5e9",
  },
  view_history: {
    label: "查看计算结果",
    icon: <TimelineRounded sx={{ fontSize: 18 }} />,
    actionLabel: "查看曲线",
    color: "#fac858",
  },
  view_scada: {
    label: "查看监测数据",
    icon: <SensorsRounded sx={{ fontSize: 18 }} />,
    actionLabel: "查看数据",
    color: "#ee6666",
  },
  show_chart: {
    label: "显示图表",
    icon: <TimelineRounded sx={{ fontSize: 18 }} />,
    actionLabel: "显示",
    color: "#73c0de",
  },
  render_junctions: {
    label: "渲染节点",
    icon: <LocationOnRounded sx={{ fontSize: 18 }} />,
    actionLabel: "应用渲染",
    color: "#3b82f6",
  },
  [APPLY_LAYER_STYLE_TOOL]: {
    label: "图层样式",
    icon: <LocationOnRounded sx={{ fontSize: 18 }} />,
    actionLabel: "应用样式",
    color: "#14b8a6",
  },
};

/* ---------- helpers ---------- */

function normalizeLocateIds(params: Record<string, unknown>): string[] {
  for (const key of LOCATE_ID_PARAM_KEYS) {
    const rawValue = params[key];
    if (Array.isArray(rawValue)) {
      const normalized = rawValue
        .map((id) => String(id).trim())
        .filter(Boolean);
      if (normalized.length > 0) {
        return normalized;
      }
    }
    if (typeof rawValue === "string" || typeof rawValue === "number") {
      const normalized = String(rawValue)
        .split(",")
        .map((id) => id.trim())
        .filter(Boolean);
      if (normalized.length > 0) {
        return normalized;
      }
    }
  }
  return [];
}

function readFiniteNumber(value: unknown): number | null {
  if (typeof value === "number" && Number.isFinite(value)) {
    return value;
  }
  if (typeof value === "string" && value.trim()) {
    const parsed = Number(value);
    return Number.isFinite(parsed) ? parsed : null;
  }
  return null;
}

function buildZoomTo3857Action(
  params: Record<string, unknown>,
): Extract<ChatToolAction, { type: "zoom_to_map" }> | null {
  const rawCoordinate = params.coordinate ?? params.coordinates ?? params.center;
  const tuple = Array.isArray(rawCoordinate)
    ? rawCoordinate
    : [params.x ?? params.lon ?? params.longitude, params.y ?? params.lat ?? params.latitude];
  const x = readFiniteNumber(tuple[0]);
  const y = readFiniteNumber(tuple[1]);
  if (x === null || y === null) {
    return null;
  }

  const zoom = readFiniteNumber(params.zoom);
  const durationMs = readFiniteNumber(params.duration_ms ?? params.durationMs);
  const rawSourceCrs = params.source_crs ?? params.sourceCrs ?? params.crs;
  const normalizedSourceCrs =
    typeof rawSourceCrs === "string" ? rawSourceCrs.trim().toUpperCase() : "";
  const sourceCrs =
    normalizedSourceCrs === "EPSG:4326" ? "EPSG:4326" : "EPSG:3857";
  return {
    type: "zoom_to_map",
    coordinate: [x, y],
    sourceCrs,
    zoom: zoom ?? undefined,
    durationMs: durationMs ?? undefined,
  };
}

function getToolDescription(toolCall: ToolCall): string {
  const { params } = toolCall;
  const resolveScadaFeatureInfos = (): [string, string][] => {
    const rawFeatureInfos = params.feature_infos;
    if (Array.isArray(rawFeatureInfos)) {
      const normalizedFeatureInfos = rawFeatureInfos
        .map((item) => (Array.isArray(item) ? item : null))
        .filter((item): item is [unknown, unknown] => Boolean(item))
        .map(
          (item) =>
            [String(item[0] ?? ""), String(item[1] ?? "scada")] as [
              string,
              string,
            ],
        )
        .filter(([id]) => id.trim().length > 0);
      if (normalizedFeatureInfos.length > 0) {
        return normalizedFeatureInfos;
      }
    }

    const rawDeviceIds =
      params.device_ids ??
      params.deviceId ??
      params.device_id ??
      params.id ??
      params.ids;
    const deviceIds = Array.isArray(rawDeviceIds)
      ? rawDeviceIds.map((id) => String(id))
      : typeof rawDeviceIds === "string"
        ? rawDeviceIds
            .split(",")
            .map((id) => id.trim())
            .filter(Boolean)
        : [];

    return deviceIds.map((id) => [id, "scada"]);
  };
  const resolveTimeRange = () => ({
    startTime:
      (params.start_time as string | undefined) ??
      (params.startTime as string | undefined) ??
      (params.from as string | undefined) ??
      (params.start as string | undefined),
    endTime:
      (params.end_time as string | undefined) ??
      (params.endTime as string | undefined) ??
      (params.to as string | undefined) ??
      (params.end as string | undefined),
  });
  const resolveLocateFeatureType = (): string => {
    const rawType = params.feature_type;
    if (typeof rawType === "string" && rawType.trim()) {
      return rawType.trim().toLowerCase();
    }
    return "";
  };
  switch (toolCall.tool) {
    case "locate_features":
    case "locate_junctions":
    case "locate_pipes":
    case "locate_valves":
    case "locate_reservoirs":
    case "locate_pumps":
    case "locate_tanks": {
      const ids = normalizeLocateIds(params);
      const idsText =
        ids.length > 3
        ? `${ids.slice(0, 3).join(", ")} 等 ${ids.length} 个`
        : ids.join(", ");
      if (toolCall.tool !== "locate_features") {
        return idsText;
      }
      const featureType = resolveLocateFeatureType();
      if (!featureType) {
        return idsText;
      }
      return idsText
        ? `${featureType} · ${idsText}`
        : featureType;
    }
    case "view_history":
    case "view_scada": {
      const infos =
        toolCall.tool === "view_scada"
          ? resolveScadaFeatureInfos()
          : ((params.feature_infos as [string, string][] | undefined) ?? []);
      const names = infos.map(([id]) => id);
      const base =
        names.length > 3
          ? `${names.slice(0, 3).join(", ")} 等 ${names.length} 个`
          : names.join(", ");
      const { startTime, endTime } = resolveTimeRange();
      if (!startTime && !endTime) {
        return base;
      }
      const rangeLabel = `时间段: ${startTime ?? "--"} ~ ${endTime ?? "--"}`;
      return base ? `${base} · ${rangeLabel}` : rangeLabel;
    }
    case "show_chart": {
      return (params.title as string | undefined) ?? "数据图表";
    }
    case "render_junctions": {
      return (params.render_ref as string | undefined) ?? "渲染引用";
    }
    case "zoom_to_map": {
      const action = buildZoomTo3857Action(params);
      if (!action) {
        return "地图坐标";
      }
      const zoom = action.zoom === undefined ? "" : ` · zoom ${action.zoom}`;
      return `${action.coordinate[0]}, ${action.coordinate[1]} · ${action.sourceCrs}${zoom}`;
    }
    case APPLY_LAYER_STYLE_TOOL: {
      const payload = parseApplyLayerStylePayload(params);
      return payload ? describeApplyLayerStyle(payload) : "图层样式";
    }
    default:
      return "";
  }
}

function buildAction(toolCall: ToolCall): ChatToolAction | null {
  const { params } = toolCall;
  const resolveScadaFeatureInfos = (): [string, string][] => {
    const rawFeatureInfos = params.feature_infos;
    if (Array.isArray(rawFeatureInfos)) {
      const normalizedFeatureInfos = rawFeatureInfos
        .map((item) => (Array.isArray(item) ? item : null))
        .filter((item): item is [unknown, unknown] => Boolean(item))
        .map(
          (item) =>
            [String(item[0] ?? ""), String(item[1] ?? "scada")] as [
              string,
              string,
            ],
        )
        .filter(([id]) => id.trim().length > 0);
      if (normalizedFeatureInfos.length > 0) {
        return normalizedFeatureInfos;
      }
    }

    const rawDeviceIds =
      params.device_ids ??
      params.deviceId ??
      params.device_id ??
      params.id ??
      params.ids;
    const deviceIds = Array.isArray(rawDeviceIds)
      ? rawDeviceIds.map((id) => String(id))
      : typeof rawDeviceIds === "string"
        ? rawDeviceIds
            .split(",")
            .map((id) => id.trim())
            .filter(Boolean)
        : [];

    return deviceIds.map((id) => [id, "scada"]);
  };
  const resolveTimeRange = () => ({
    startTime:
      (params.start_time as string | undefined) ??
      (params.startTime as string | undefined) ??
      (params.from as string | undefined) ??
      (params.start as string | undefined),
    endTime:
      (params.end_time as string | undefined) ??
      (params.endTime as string | undefined) ??
      (params.to as string | undefined) ??
      (params.end as string | undefined),
  });
  switch (toolCall.tool) {
    case "zoom_to_map":
      return buildZoomTo3857Action(params);
    case "locate_features": {
      const featureTypeRaw = params.feature_type;
      const featureType =
        typeof featureTypeRaw === "string"
          ? featureTypeRaw.trim().toLowerCase()
          : "";
      const config = locateFeatureTypeToConfig(featureType);
        if (!config) return null;
        return {
          type: "locate_features",
          ids: normalizeLocateIds(params),
          layer: config.layer,
          geometryKind: config.geometryKind,
        };
    }
    case "locate_junctions":
    case "locate_pipes":
    case "locate_valves":
    case "locate_reservoirs":
    case "locate_pumps":
    case "locate_tanks": {
      const layer = LOCATE_TOOL_TO_LAYER[toolCall.tool];
      if (!layer) return null;
      return {
        type: "locate_features",
        ids: normalizeLocateIds(params),
        layer,
        geometryKind: LOCATE_LINE_TOOLS.has(toolCall.tool) ? "line" : "point",
      };
    }
    case "view_history": {
      const historyRange = resolveTimeRange();
      return {
        type: "view_history",
        featureInfos:
          (params.feature_infos as [string, string][] | undefined) ?? [],
        dataType:
          (params.data_type as "realtime" | "scheme" | "none" | undefined) ??
          "realtime",
        startTime: historyRange.startTime,
        endTime: historyRange.endTime,
      };
    }
    case "view_scada": {
      const scadaRange = resolveTimeRange();
      return {
        type: "view_scada",
        featureInfos: resolveScadaFeatureInfos(),
        startTime: scadaRange.startTime,
        endTime: scadaRange.endTime,
      };
    }
    case "show_chart":
      return {
        type: "show_chart",
        title: params.title as string | undefined,
        chartType:
          (params.chart_type as "line" | "bar" | "pie" | undefined) ?? "line",
        xData: (params.x_data as string[] | undefined) ?? [],
        series:
          (params.series as
            | Array<{ name: string; data: number[]; type?: "line" | "bar" }>
            | undefined) ?? [],
        xAxisName: params.x_axis_name as string | undefined,
        yAxisName: params.y_axis_name as string | undefined,
      };
    case "render_junctions": {
      const renderRef =
        typeof params.render_ref === "string" ? params.render_ref.trim() : "";
      if (!renderRef) {
        return null;
      }
      return {
        type: "render_junctions",
        renderRef,
      };
    }
    case APPLY_LAYER_STYLE_TOOL: {
      const payload = parseApplyLayerStylePayload(params);
      if (!payload) {
        return null;
      }
      return {
        type: "apply_layer_style",
        layerId: payload.layerId,
        resetToDefault: payload.resetToDefault,
        styleConfig: payload.styleConfig,
      };
    }
    default:
      return null;
  }
}

/* ---------- component ---------- */

export interface ChatToolCallBlockProps {
  toolCall: ToolCall;
}

export const ChatToolCallBlock: React.FC<ChatToolCallBlockProps> = ({
  toolCall,
}) => {
  const theme = useTheme();
  const dispatch = useChatToolStore((s) => s.dispatch);
  const [executed, setExecuted] = useState(false);
  const [expanded, setExpanded] = useState(false);

  const meta: ToolMeta = TOOL_META[toolCall.tool] ?? {
    label: toolCall.tool,
    icon: <TimelineRounded sx={{ fontSize: 18 }} />,
    actionLabel: "执行",
    color: "#00acc1",
  };

  const description = getToolDescription(toolCall);

  const handleExecute = useCallback(() => {
    const action = buildAction(toolCall);
    if (action) {
      dispatch(action);
      setExecuted(true);
    }
  }, [toolCall, dispatch]);

  return (
    <Paper
      elevation={0}
      sx={{
        mt: 1,
        mb: 1,
        overflow: "hidden",
        borderRadius: 4,
        border: `1px solid ${alpha(meta.color, 0.3)}`,
        bgcolor: alpha(meta.color, 0.05),
        backdropFilter: "blur(12px)",
        transition: "all 0.3s ease",
        "&:hover": {
          bgcolor: alpha(meta.color, 0.08),
          border: `1px solid ${alpha(meta.color, 0.4)}`,
        }
      }}
    >
      <Box
        onClick={() => setExpanded(!expanded)}
        sx={{
          p: 1.5,
          display: "flex",
          alignItems: "center",
          cursor: "pointer",
          gap: 1.5,
        }}
      >
        {/* Icon */}
        <Box
          sx={{
            width: 32,
            height: 32,
            borderRadius: "50%",
            bgcolor: alpha(meta.color, 0.15),
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
            color: meta.color,
            flexShrink: 0,
            boxShadow: `0 2px 8px ${alpha(meta.color, 0.2)}`,
          }}
        >
          {meta.icon}
        </Box>

        {/* Title */}
        <Box sx={{ flex: 1, minWidth: 0, display: "flex", alignItems: "center", gap: 1 }}>
          <Typography
            variant="body2"
            sx={{
              fontWeight: 700,
              color: "text.primary",
            }}
          >
            {meta.label}
          </Typography>
          {!expanded && description && (
             <Typography
             variant="caption"
             sx={{
               color: "text.secondary",
               fontSize: "0.75rem",
               overflow: "hidden",
               textOverflow: "ellipsis",
               whiteSpace: "nowrap",
               maxWidth: 180,
               opacity: 0.8,
             }}
           >
             • {description}
           </Typography>
          )}
        </Box>

        <IconButton size="small" sx={{ color: "text.secondary", width: 28, height: 28, pointerEvents: "none" }}>
          {expanded ? <KeyboardArrowUpRounded fontSize="small" /> : <KeyboardArrowDownRounded fontSize="small" />}
        </IconButton>
      </Box>

      <Collapse in={expanded} timeout="auto" unmountOnExit>
        <Box sx={{ px: 1.5, pb: 1.5, pt: 0 }}>
          <Stack direction="column" spacing={1.5}>
            {description && (
               <Box sx={{ 
                 p: 1.5, 
                 borderRadius: 3, 
                 bgcolor: alpha("#000", 0.03), 
                 border: `1px solid ${alpha("#000", 0.05)}`,
               }}>
                 <Typography variant="caption" color="text.secondary" fontWeight={700} sx={{ mb: 0.5, display: 'block' }}>
                   执行参数
                 </Typography>
                 <Typography variant="body2" color="text.primary" sx={{ wordBreak: 'break-word', fontFamily: 'monospace', fontSize: '0.8rem' }}>
                    {description}
                 </Typography>
               </Box>
            )}

            <Stack direction="row" justifyContent="flex-end">
              {executed ? (
                <Chip
                  icon={<CheckCircleRounded sx={{ fontSize: 16 }} />}
                  label="已执行"
                  size="small"
                  sx={{
                    bgcolor: alpha("#00e676", 0.15),
                    color: "#00c853",
                    fontWeight: 700,
                    fontSize: "0.75rem",
                  }}
                />
              ) : (
                <Button
                  size="small"
                  variant="contained"
                  disableElevation
                  onClick={(e) => { e.stopPropagation(); handleExecute(); }}
                  sx={{
                    bgcolor: meta.color,
                    color: "#fff",
                    fontWeight: 700,
                    fontSize: "0.8rem",
                    borderRadius: 2.5,
                    px: 2,
                    textTransform: "none",
                    boxShadow: `0 4px 12px ${alpha(meta.color, 0.3)}`,
                    "&:hover": {
                      bgcolor: meta.color,
                      filter: "brightness(0.9)",
                      boxShadow: `0 6px 16px ${alpha(meta.color, 0.4)}`,
                    },
                  }}
                >
                  {meta.actionLabel}
                </Button>
              )}
            </Stack>
          </Stack>
        </Box>
      </Collapse>
    </Paper>
  );
};
  const locateFeatureTypeToConfig = (
    featureType: string,
  ): { layer: string; geometryKind: "point" | "line" } | null => {
    switch (featureType) {
      case "junction":
      case "junctions":
        return { layer: "geo_junctions_mat", geometryKind: "point" };
      case "pipe":
      case "pipes":
        return { layer: "geo_pipes_mat", geometryKind: "line" };
      case "valve":
      case "valves":
        return { layer: "geo_valves", geometryKind: "point" };
      case "reservoir":
      case "reservoirs":
        return { layer: "geo_reservoirs", geometryKind: "point" };
      case "pump":
      case "pumps":
        return { layer: "geo_pumps", geometryKind: "point" };
      case "tank":
      case "tanks":
        return { layer: "geo_tanks", geometryKind: "point" };
      default:
        return null;
    }
  };
