import { SCADA_FIELDS, type ElementType } from "../core/constants.js";
import { CliError } from "../core/errors.js";
import { emitApi } from "../core/http.js";
import { fieldsFor, optionalString, parseOptions, requiredString, requiredStringArray, validateChoice } from "../core/options.js";
import { resolveScheme } from "../core/runtime.js";
import { parseTime } from "../core/time.js";
import type { HandlerMap, RuntimeContext } from "../core/types.js";

function rangeGet(ctx: RuntimeContext, argv: string[], summary: string, path: string): Promise<void> {
  const { values } = parseOptions(argv);
  return emitApi(ctx, summary, {
    method: "GET",
    path,
    params: { start_time: parseTime(requiredString(values, "start-time"), "--start-time"), end_time: parseTime(requiredString(values, "end-time"), "--end-time") },
    requireProject: true,
  });
}

function realtimeByIdTime(ctx: RuntimeContext, argv: string[]): Promise<void> {
  const { values } = parseOptions(argv);
  return emitApi(ctx, "读取实时模拟数据成功", {
    method: "GET",
    path: "/timeseries/realtime/simulation-results",
    params: { id: requiredString(values, "id"), type: validateChoice(requiredString(values, "type"), ["pipe", "junction"] as const, "--type"), query_time: parseTime(requiredString(values, "time"), "--time") },
    requireProject: true,
  });
}

function realtimeByTimeProperty(ctx: RuntimeContext, argv: string[]): Promise<void> {
  const { values } = parseOptions(argv);
  const type = validateChoice(requiredString(values, "type"), ["pipe", "junction"] as const, "--type");
  return emitApi(ctx, "读取实时属性聚合数据成功", {
    method: "GET",
    path: "/timeseries/realtime/records",
    params: { type, query_time: parseTime(requiredString(values, "time"), "--time"), property: validateChoice(requiredString(values, "property"), fieldsFor(type), "--property") },
    requireProject: true,
  });
}

function schemeLinks(ctx: RuntimeContext, argv: string[]): Promise<void> {
  const { values } = parseOptions(argv);
  return emitApi(ctx, "读取方案管道数据成功", {
    method: "GET",
    path: "/timeseries/schemes/links",
    params: {
      scheme_name: resolveScheme(ctx, optionalString(values, "scheme"), true),
      scheme_type: optionalString(values, "scheme-type") || "simulation",
      start_time: parseTime(requiredString(values, "start-time"), "--start-time"),
      end_time: parseTime(requiredString(values, "end-time"), "--end-time"),
    },
    requireProject: true,
  });
}

function schemeNodeField(ctx: RuntimeContext, argv: string[]): Promise<void> {
  const { values } = parseOptions(argv);
  return emitApi(ctx, "读取方案节点字段成功", {
    method: "GET",
    path: `/timeseries/schemes/nodes/${requiredString(values, "node")}/field`,
    params: {
      field: validateChoice(requiredString(values, "field"), fieldsFor("junction"), "--field"),
      scheme_name: resolveScheme(ctx, optionalString(values, "scheme"), true),
      scheme_type: optionalString(values, "scheme-type") || "simulation",
      start_time: parseTime(requiredString(values, "start-time"), "--start-time"),
      end_time: parseTime(requiredString(values, "end-time"), "--end-time"),
    },
    requireProject: true,
  });
}

function schemeSimulation(ctx: RuntimeContext, argv: string[]): Promise<void> {
  const { values } = parseOptions(argv);
  const query = validateChoice(requiredString(values, "query"), ["by-id-time", "by-scheme-time-property"] as const, "--query");
  const type = validateChoice(optionalString(values, "type") || "pipe", ["pipe", "junction"] as const, "--type") as ElementType;
  const params: Record<string, unknown> = {
    scheme_name: resolveScheme(ctx, optionalString(values, "scheme"), true),
    scheme_type: optionalString(values, "scheme-type") || "simulation",
    query_time: parseTime(requiredString(values, "time"), "--time"),
    type,
  };
  if (query === "by-id-time") {
    params.id = requiredString(values, "id");
    return emitApi(ctx, "读取方案单点模拟数据成功", { method: "GET", path: "/timeseries/schemes/simulation-results", params, requireProject: true });
  }
  params.property = validateChoice(requiredString(values, "property"), fieldsFor(type), "--property");
  return emitApi(ctx, "读取方案属性聚合数据成功", { method: "GET", path: "/timeseries/schemes/records", params, requireProject: true });
}

function scadaQuery(ctx: RuntimeContext, argv: string[]): Promise<void> {
  const { values } = parseOptions(argv, { "device-id": "repeat" });
  const params: Record<string, unknown> = {
    device_ids: requiredStringArray(values, "device-id").join(","),
    start_time: parseTime(requiredString(values, "start-time"), "--start-time"),
    end_time: parseTime(requiredString(values, "end-time"), "--end-time"),
  };
  const field = optionalString(values, "field");
  if (field) params.field = validateChoice(field, SCADA_FIELDS, "--field");
  return emitApi(ctx, "读取 SCADA 时序成功", { method: "GET", path: field ? "/timeseries/scada-readings/fields" : "/timeseries/scada-readings", params, requireProject: true });
}

function composite(ctx: RuntimeContext, argv: string[]): Promise<void> {
  const { values } = parseOptions(argv, { feature: "repeat", "use-cleaned": "boolean" });
  const kind = validateChoice(requiredString(values, "kind"), ["scada-simulation", "element-simulation", "element-scada"] as const, "--kind");
  const params: Record<string, unknown> = {
    start_time: parseTime(requiredString(values, "start-time"), "--start-time"),
    end_time: parseTime(requiredString(values, "end-time"), "--end-time"),
  };
  const schemeName = resolveScheme(ctx, optionalString(values, "scheme"));
  if (schemeName) Object.assign(params, { scheme_name: schemeName, scheme_type: optionalString(values, "scheme-type") || "simulation" });
  if (kind === "scada-simulation") params.device_ids = requiredStringArray(values, "feature").join(",");
  else if (kind === "element-simulation") params.feature_infos = requiredStringArray(values, "feature").join(",");
  else {
    const feature = requiredStringArray(values, "feature");
    if (feature.length !== 1) throw new CliError("CLI 参数错误", "FEATURE_REQUIRED", "element-scada requires exactly one --feature as element_id", 2);
    params.element_id = feature[0];
    params.use_cleaned = Boolean(values["use-cleaned"]);
  }
  const paths = {
    "scada-simulation": "/timeseries/views/scada-simulations",
    "element-simulation": "/timeseries/views/element-simulations",
    "element-scada": "/timeseries/views/element-scada-readings",
  } as const;
  return emitApi(ctx, kind === "scada-simulation" ? "读取复合 SCADA-模拟数据成功" : kind === "element-simulation" ? "读取复合元素模拟数据成功" : "读取元素关联 SCADA 数据成功", { method: "GET", path: paths[kind], params, requireProject: true });
}

function pipelineHealth(ctx: RuntimeContext, argv: string[]): Promise<void> {
  const { values } = parseOptions(argv);
  requiredString(values, "pipe");
  requiredString(values, "start-time");
  return emitApi(ctx, "读取管道健康预测成功", {
    method: "GET",
    path: "/pipeline-health-predictions",
    params: { query_time: parseTime(requiredString(values, "end-time"), "--end-time") },
    requireProject: true,
  });
}

function dataScadaGet(ctx: RuntimeContext, argv: string[]): Promise<void> {
  const { values } = parseOptions(argv);
  validateChoice(requiredString(values, "kind"), ["info"] as const, "--kind");
  return emitApi(ctx, "读取 SCADA 数据成功", { method: "GET", path: "/scada-info/detail", params: { id: requiredString(values, "id") }, requireProject: true });
}

function dataScadaList(ctx: RuntimeContext, argv: string[]): Promise<void> {
  const { values } = parseOptions(argv);
  validateChoice(requiredString(values, "kind"), ["info"] as const, "--kind");
  return emitApi(ctx, "读取 SCADA 列表成功", { method: "GET", path: "/scada-info", requireProject: true });
}

function dataSchemeGet(ctx: RuntimeContext, argv: string[]): Promise<void> {
  const { values } = parseOptions(argv);
  return emitApi(ctx, "读取方案成功", { method: "GET", path: "/schemes/detail", params: { schema_name: requiredString(values, "name") }, requireProject: true });
}

export const dataHandlers: HandlerMap = {
  "data timeseries realtime links": (ctx, argv) => rangeGet(ctx, argv, "读取实时管道数据成功", "/timeseries/realtime/links"),
  "data timeseries realtime nodes": (ctx, argv) => rangeGet(ctx, argv, "读取实时节点数据成功", "/timeseries/realtime/nodes"),
  "data timeseries realtime simulation-by-id-time": realtimeByIdTime,
  "data timeseries realtime simulation-by-time-property": realtimeByTimeProperty,
  "data timeseries scheme links": schemeLinks,
  "data timeseries scheme node-field": schemeNodeField,
  "data timeseries scheme simulation": schemeSimulation,
  "data timeseries scada query": scadaQuery,
  "data timeseries composite": composite,
  "data timeseries composite pipeline-health": pipelineHealth,
  "data scada get": dataScadaGet,
  "data scada list": dataScadaList,
  "data scheme schema": (ctx) => emitApi(ctx, "读取方案 schema 成功", { method: "GET", path: "/network-schemas/scheme", requireProject: true }),
  "data scheme get": dataSchemeGet,
  "data scheme list": (ctx) => emitApi(ctx, "读取方案列表成功", { method: "GET", path: "/schemes", requireProject: true }),
};
