import Feature from "ol/Feature";

import { FLOW_DISPLAY_UNIT, toM3h } from "@utils/units";

type ToolbarBaseProperty = {
  label: string;
  value: string | number;
  unit?: string;
  formatter?: (value: string | number) => string;
};

type ToolbarTableProperty = {
  type: "table";
  label: string;
  columns: string[];
  rows: (string | number)[][];
};

type ToolbarSelectProperty = {
  type: "select";
  label: string;
  value: string;
  options: { label: string; value: string }[];
  placeholder?: string;
  disabled?: boolean;
  saving?: boolean;
  onSave: (value: string) => Promise<void>;
};

type ToolbarTextProperty = {
  type: "text";
  label: string;
  value: string;
  placeholder?: string;
  disabled?: boolean;
  saving?: boolean;
  helperText?: string;
  onSave: (value: string) => Promise<void>;
};

export type ToolbarPropertyItem =
  | ToolbarBaseProperty
  | ToolbarTableProperty
  | ToolbarSelectProperty
  | ToolbarTextProperty;

export type ToolbarPropertyPanelData = {
  id?: string;
  type?: string;
  properties?: ToolbarPropertyItem[];
};

export type ValveStatusPropertyOptions = {
  value: string | null;
  loading?: boolean;
  saving?: boolean;
  onSave: (value: string) => Promise<void>;
};

export type ValveSettingPropertyOptions = {
  value: string | null;
  vType: string | null;
  loading?: boolean;
  saving?: boolean;
  status?: string | null;
  onSave: (value: string) => Promise<void>;
};

const getValveSettingHelperText = (
  vType: string | null,
  status?: string | null,
) => {
  if (status === "OPEN" || status === "CLOSED") {
    return "开启/关闭状态下 EPANET 会忽略阀门设置值";
  }

  switch (vType?.toUpperCase()) {
    case "PRV":
    case "PSV":
    case "PBV":
      return "压力设置值，需为 0 或正数";
    case "FCV":
      return "流量设置值，需为 0 或正数";
    case "TCV":
      return "损失系数，需为 0 或正数";
    case "GPV":
      return "水头损失曲线 ID";
    default:
      return "阀门类型相关设置值";
  }
};

const getFeatureHistoryType = (feature: Feature): string | null => {
  const layerId = feature.getId()?.toString().split(".")[0] || "";
  if (layerId.includes("pipe")) return "pipe";
  if (layerId.includes("junction")) return "junction";
  if (layerId.includes("tank")) return "tank";
  if (layerId.includes("reservoir")) return "reservoir";
  if (layerId.includes("pump")) return "pump";
  if (layerId.includes("valve")) return "valve";
  return null;
};

export const inferHistoryFeatureInfos = (
  highlightFeatures: Feature[],
): [string, string][] =>
  highlightFeatures
    .map((feature) => {
      const properties = feature.getProperties();
      const id = properties.id;
      if (!id) return null;

      const type = getFeatureHistoryType(feature);
      if (type !== "pipe" && type !== "junction") {
        return null;
      }

      return [id, type] as [string, string];
    })
    .filter(Boolean) as [string, string][];

export const buildFeatureProperties = (
  highlightFeature: Feature | undefined,
  computedProperties: Record<string, any>,
  valveStatus?: ValveStatusPropertyOptions,
  valveSetting?: ValveSettingPropertyOptions,
): ToolbarPropertyPanelData => {
  if (!highlightFeature) return {};

  const layer = highlightFeature.getId()?.toString().split(".")[0];
  const properties = highlightFeature.getProperties();
  const pipeComputedFields = [
    { key: "flow", label: "流量", unit: `${FLOW_DISPLAY_UNIT}` },
    { key: "friction", label: "摩阻", unit: "" },
    { key: "headloss", label: "水头损失", unit: "m" },
    { key: "unit_headloss", label: "单位水头损失", unit: "m/km" },
    { key: "quality", label: "水质", unit: "mg/L" },
    { key: "reaction", label: "反应", unit: "1/d" },
    { key: "setting", label: "设置", unit: "" },
    { key: "status", label: "状态", unit: "" },
    { key: "velocity", label: "流速", unit: "m/s" },
  ];
  const nodeComputedFields = [
    { key: "actual_demand", label: "实际需水量", unit: `${FLOW_DISPLAY_UNIT}` },
    { key: "total_head", label: "水头", unit: "m" },
    { key: "pressure", label: "压力", unit: "m" },
    { key: "quality", label: "水质", unit: "mg/L" },
  ];

  if (layer === "geo_pipes_mat" || layer === "geo_pipes") {
    const result: ToolbarPropertyPanelData = {
      id: properties.id,
      type: "管道",
      properties: [
        { label: "起始节点ID", value: properties.node1 },
        { label: "终点节点ID", value: properties.node2 },
        { label: "长度", value: properties.length?.toFixed?.(1), unit: "m" },
        {
          label: "管径",
          value: properties.diameter?.toFixed?.(1),
          unit: "mm",
        },
        { label: "粗糙度", value: properties.roughness },
        { label: "局部损失", value: properties.minor_loss },
        { label: "初始状态", value: "开" },
      ],
    };

    pipeComputedFields.forEach(({ key, label, unit }) => {
      let value = computedProperties[key];

      if (key === "flow" && value !== undefined) {
        value = toM3h(value, "lps");
      }

      if (
        key === "unit_headloss" &&
        value === undefined &&
        computedProperties.headloss !== undefined &&
        properties.length
      ) {
        value = (computedProperties.headloss / properties.length) * 1000;
      }

      if (value !== undefined) {
        result.properties?.push({
          label,
          value: typeof value === "number" ? value.toFixed(3) : value,
          unit,
        });
      }
    });

    return result;
  }

  if (layer === "geo_junctions_mat" || layer === "geo_junctions") {
    const result: ToolbarPropertyPanelData = {
      id: properties.id,
      type: "节点",
      properties: [
        {
          label: "高程",
          value: properties.elevation?.toFixed?.(1),
          unit: "m",
        },
        {
          type: "table",
          label: "基本需水量",
          columns: ["demand", "pattern"],
          rows: Array.from({ length: 5 }, (_, i) => i + 1)
            .map((idx) => {
              let demand = properties?.[`demand${idx}`];
              const pattern = properties?.[`pattern${idx}`];
              if (
                demand !== undefined &&
                demand !== null &&
                demand !== ""
              ) {
                demand = toM3h(Number(demand), "lps");
                return [
                  typeof demand === "number" ? demand.toFixed(3) : demand,
                  pattern ?? "-",
                ];
              }
              return null;
            })
            .filter(Boolean) as (string | number)[][],
        },
      ],
    };

    nodeComputedFields.forEach(({ key, label, unit }) => {
      if (computedProperties[key] !== undefined) {
        let value = computedProperties[key];
        if (key === "actual_demand") {
          value = toM3h(value, "lps");
        }
        result.properties?.push({
          label,
          value: value?.toFixed?.(3) || value,
          unit,
        });
      }
    });

    return result;
  }

  if (layer === "geo_tanks_mat" || layer === "geo_tanks") {
    return {
      id: properties.id,
      type: "水池",
      properties: [
        {
          label: "高程",
          value: properties.elevation?.toFixed?.(1),
          unit: "m",
        },
        {
          label: "初始水位",
          value: properties.init_level?.toFixed?.(1),
          unit: "m",
        },
        {
          label: "最低水位",
          value: properties.min_level?.toFixed?.(1),
          unit: "m",
        },
        {
          label: "最高水位",
          value: properties.max_level?.toFixed?.(1),
          unit: "m",
        },
        {
          label: "直径",
          value: properties.diameter?.toFixed?.(1),
          unit: "m",
        },
        {
          label: "最小容积",
          value: properties.min_vol?.toFixed?.(1),
          unit: "m³",
        },
        {
          label: "溢出",
          value: properties.overflow ? "是" : "否",
        },
      ],
    };
  }

  if (layer === "geo_reservoirs_mat" || layer === "geo_reservoirs") {
    return {
      id: properties.id,
      type: "水库",
      properties: [
        {
          label: "水头",
          value: properties.head?.toFixed?.(1),
          unit: "m",
        },
      ],
    };
  }

  if (layer === "geo_pumps_mat" || layer === "geo_pumps") {
    return {
      id: properties.id,
      type: "水泵",
      properties: [
        { label: "起始节点 ID", value: properties.node1 },
        { label: "终点节点 ID", value: properties.node2 },
        {
          label: "功率",
          value: properties.power?.toFixed?.(1),
          unit: "kW",
        },
        {
          label: "扬程",
          value: properties.head?.toFixed?.(1),
          unit: "m",
        },
        {
          label: "转速",
          value: properties.speed?.toFixed?.(1),
          unit: "rpm",
        },
        {
          label: "模式",
          value: properties.pattern,
        },
      ],
    };
  }

  if (layer === "geo_valves_mat" || layer === "geo_valves") {
    const valveType = valveSetting?.vType ?? properties.v_type;
    const isValveSettingDisabled =
      valveSetting?.loading ||
      valveSetting?.status === "OPEN" ||
      valveSetting?.status === "CLOSED";

    return {
      id: properties.id,
      type: "阀门",
      properties: [
        { label: "起始节点 ID", value: properties.node1 },
        { label: "终点节点 ID", value: properties.node2 },
        {
          label: "直径",
          value: properties.diameter?.toFixed?.(1),
          unit: "mm",
        },
        {
          label: "阀门类型",
          value: valveType,
        },
        {
          label: "局部损失",
          value: properties.minor_loss?.toFixed?.(2),
        },
        ...(valveStatus
          ? [
              {
                type: "select" as const,
                label: "开关状态",
                value: valveStatus.value ?? "",
                options: [
                  { label: "开启", value: "OPEN" },
                  { label: "关闭", value: "CLOSED" },
                  { label: "激活", value: "ACTIVE" },
                ],
                placeholder: valveStatus.loading ? "加载中" : "未设置",
                disabled: valveStatus.loading,
                saving: valveStatus.saving,
                onSave: valveStatus.onSave,
              },
            ]
          : []),
        ...(valveSetting
          ? [
              {
                type: "text" as const,
                label: "阀门设置值",
                value: valveSetting.value ?? "",
                placeholder: valveSetting.loading ? "加载中" : "未设置",
                disabled: isValveSettingDisabled,
                saving: valveSetting.saving,
                helperText: getValveSettingHelperText(
                  valveType,
                  valveSetting.status,
                ),
                onSave: valveSetting.onSave,
              },
            ]
          : []),
      ],
    };
  }

  const getTransmissionFrequency = (transmissionFrequency: string) => {
    const parts = transmissionFrequency.split(":");
    if (parts.length !== 3) return transmissionFrequency;
    const hours = parseInt(parts[0], 10);
    const minutes = parseInt(parts[1], 10);
    const seconds = parseInt(parts[2], 10);
    return hours * 60 + minutes + (seconds >= 30 ? 1 : 0);
  };

  const getReliability = (reliability: number) => {
    switch (reliability) {
      case 1:
        return "高";
      case 2:
        return "中";
      case 3:
        return "低";
      default:
        return "未知";
    }
  };

  if (layer === "geo_scada_mat" || layer === "geo_scada") {
    return {
      id: properties.id,
      type: "SCADA设备",
      properties: [
        {
          label: "类型",
          value:
            properties.type === "pipe_flow" ? "流量传感器" : "压力传感器",
        },
        {
          label: "关联节点 ID",
          value: properties.associated_element_id,
        },
        {
          label: "传输模式",
          value:
            properties.transmission_mode === "non_realtime"
              ? "定时传输"
              : "实时传输",
        },
        {
          label: "传输频率",
          value: getTransmissionFrequency(properties.transmission_frequency),
          unit: "分钟",
        },
        {
          label: "可靠性",
          value: getReliability(properties.reliability),
        },
      ],
    };
  }

  return {};
};
