import { CliError } from "../core/errors.js";
import { emitApi, requestJson } from "../core/http.js";
import { assignDatasetKeys, parseBurstFile, parseValveSettingFile } from "../core/files.js";
import { optionalNumber, optionalString, optionalStringArray, parseOptions, requiredNumber, requiredString, validateChoice } from "../core/options.js";
import { resolveScheme } from "../core/runtime.js";
import { parseTime } from "../core/time.js";
import { success } from "../core/output.js";
import type { HandlerMap, RuntimeContext } from "../core/types.js";

function analysisBurst(ctx: RuntimeContext, argv: string[]): Promise<void> {
  const { values } = parseOptions(argv, { duration: "integer" });
  const [ids, sizes] = parseBurstFile(requiredString(values, "burst-file"));
  const schemeName = resolveScheme(ctx, optionalString(values, "scheme"), true)!;
  return emitApi(ctx, "爆管分析执行成功", {
    method: "POST",
    path: "/burst-analyses",
    params: {
      modify_pattern_start_time: parseTime(requiredString(values, "start-time"), "--start-time"),
      burst_id: ids,
      burst_size: sizes,
      modify_total_duration: requiredNumber(values, "duration"),
      scheme_name: schemeName,
    },
    requireProject: true,
  }, [`tjwater-cli data scheme get --name ${schemeName}`, "tjwater-cli data scheme list"]);
}

function analysisValve(ctx: RuntimeContext, argv: string[]): Promise<void> {
  const { values } = parseOptions(argv, { valve: "repeat", element: "repeat", "disabled-valve": "repeat", duration: "integer" });
  const mode = validateChoice(requiredString(values, "mode"), ["close", "isolation"] as const, "--mode");
  if (mode === "close") {
    const valves = optionalStringArray(values, "valve");
    const startTime = optionalString(values, "start-time");
    if (!startTime || !valves) throw new CliError("CLI 参数错误", "INVALID_VALVE_CLOSE_ARGS", "close mode requires --start-time and at least one --valve", 2);
    return emitApi(ctx, "阀门关闭分析执行成功", {
      method: "POST",
      path: "/valve-isolation-analyses",
      params: {
        start_time: parseTime(startTime, "--start-time"),
        valves,
        duration: optionalNumber(values, "duration") || 900,
        scheme_name: resolveScheme(ctx, optionalString(values, "scheme"), true),
      },
      requireProject: true,
    });
  }
  const elements = optionalStringArray(values, "element");
  if (!elements) throw new CliError("CLI 参数错误", "INVALID_VALVE_ISOLATION_ARGS", "isolation mode requires at least one --element", 2);
  return emitApi(ctx, "阀门隔离分析执行成功", {
    method: "POST",
    path: "/valve-isolation-analyses",
    params: { accident_element: elements, disabled_valves: optionalStringArray(values, "disabled-valve") },
    requireProject: true,
  });
}

function analysisFlushing(ctx: RuntimeContext, argv: string[]): Promise<void> {
  const { values } = parseOptions(argv, { flow: "number", duration: "integer" });
  const [valves, openings] = parseValveSettingFile(requiredString(values, "valve-setting-file"));
  return emitApi(ctx, "冲洗分析执行成功", {
    method: "POST",
    path: "/flushing-analyses",
    params: {
      start_time: parseTime(requiredString(values, "start-time"), "--start-time"),
      valves,
      valves_k: openings,
      drainage_node_id: requiredString(values, "drainage-node"),
      flush_flow: requiredNumber(values, "flow"),
      duration: optionalNumber(values, "duration") || 900,
      scheme_name: resolveScheme(ctx, optionalString(values, "scheme"), true),
    },
    requireProject: true,
  });
}

function analysisAge(ctx: RuntimeContext, argv: string[]): Promise<void> {
  const { values } = parseOptions(argv, { duration: "integer" });
  return emitApi(ctx, "水龄分析执行成功", {
    method: "POST",
    path: "/water-age-analyses",
    params: { start_time: parseTime(requiredString(values, "start-time"), "--start-time"), duration: requiredNumber(values, "duration") },
    requireProject: true,
  });
}

function analysisContaminant(ctx: RuntimeContext, argv: string[]): Promise<void> {
  const { values } = parseOptions(argv, { duration: "integer", concentration: "number" });
  const params: Record<string, unknown> = {
    start_time: parseTime(requiredString(values, "start-time"), "--start-time"),
    source: requiredString(values, "source-node"),
    concentration: requiredNumber(values, "concentration"),
    duration: requiredNumber(values, "duration"),
    scheme_name: resolveScheme(ctx, optionalString(values, "scheme"), true),
  };
  const pattern = optionalString(values, "pattern");
  if (pattern) params.pattern = pattern;
  return emitApi(ctx, "污染物模拟执行成功", { method: "POST", path: "/contaminant-simulations", params, requireProject: true });
}

function sensorKmeans(ctx: RuntimeContext, argv: string[]): Promise<void> {
  const { values } = parseOptions(argv, { count: "integer", "min-diameter": "integer" });
  return emitApi(ctx, "传感器选址执行成功", {
    method: "POST",
    path: "/pressure-sensor-placement-kmeans",
    body: {
      scheme_name: resolveScheme(ctx, optionalString(values, "scheme"), true),
      sensor_number: requiredNumber(values, "count"),
      min_diameter: optionalNumber(values, "min-diameter") || 0,
    },
    requireProject: true,
  });
}

function schemeAnalysis(ctx: RuntimeContext, argv: string[], summary: string, path: string, startKey: string, endKey: string): Promise<void> {
  const { values } = parseOptions(argv);
  return emitApi(ctx, summary, {
    method: "POST",
    path,
    body: {
      [startKey]: parseTime(requiredString(values, "start-time"), "--start-time"),
      [endKey]: parseTime(requiredString(values, "end-time"), "--end-time"),
      scheme_name: resolveScheme(ctx, optionalString(values, "scheme"), true),
    },
    requireProject: true,
  });
}

function schemeList(ctx: RuntimeContext, summary: string, schemeType: string): Promise<void> {
  return emitApi(ctx, summary, { method: "GET", path: "/schemes", params: { scheme_type: schemeType }, requireProject: true });
}

function schemeGet(ctx: RuntimeContext, argv: string[], summary: string, schemeType: string): Promise<void> {
  const { positionals } = parseOptions(argv);
  if (!positionals[0]) throw new CliError("CLI 参数错误", "MISSING_ARGUMENT", "Missing argument 'SCHEME_NAME'", 2);
  return emitApi(ctx, summary, { method: "GET", path: `/schemes/${positionals[0]}`, params: { scheme_type: schemeType }, requireProject: true });
}

function burstLocation(ctx: RuntimeContext, argv: string[]): Promise<void> {
  const { values } = parseOptions(argv, { "burst-leakage": "number", "pressure-scada-id": "repeat", "flow-scada-id": "repeat", "use-scada-flow": "boolean" });
  const body: Record<string, unknown> = {
    scheme_name: resolveScheme(ctx, optionalString(values, "scheme"), true),
    data_source: optionalString(values, "data-source") || "monitoring",
    scada_burst_start: parseTime(requiredString(values, "start-time"), "--start-time"),
    scada_burst_end: parseTime(requiredString(values, "end-time"), "--end-time"),
    burst_leakage: requiredNumber(values, "burst-leakage"),
    use_scada_flow: Boolean(values["use-scada-flow"]),
  };
  const pressureIds = optionalStringArray(values, "pressure-scada-id");
  const flowIds = optionalStringArray(values, "flow-scada-id");
  if (pressureIds) body.pressure_scada_ids = pressureIds;
  if (flowIds) body.flow_scada_ids = flowIds;
  const pressureFile = optionalString(values, "pressure-file");
  const flowFile = optionalString(values, "flow-file");
  if (pressureFile) assignDatasetKeys(body, pressureFile, ["burst_pressure", "normal_pressure"], "pressure");
  if (flowFile) assignDatasetKeys(body, flowFile, ["burst_flow", "normal_flow"], "flow");
  return emitApi(ctx, "爆管定位执行成功", { method: "POST", path: "/burst-locations", body, requireProject: true });
}

function riskPipe(ctx: RuntimeContext, argv: string[], summary: string, path: string): Promise<void> {
  const { values } = parseOptions(argv);
  return emitApi(ctx, summary, { method: "GET", path, params: { pipe_id: requiredString(values, "pipe") }, requireProject: true });
}

async function riskNetwork(ctx: RuntimeContext): Promise<void> {
  const [probabilities, a] = await requestJson(ctx, { method: "GET", path: "/network-pipe-risk-probability-nows", requireProject: true });
  const [geometries, b] = await requestJson(ctx, { method: "GET", path: "/pipes/risk-probability-geometries", requireProject: true });
  success("读取全网风险成功", { probabilities, geometries }, ctx, a + b);
}

export const analysisHandlers: HandlerMap = {
  "analysis burst": analysisBurst,
  "analysis valve": analysisValve,
  "analysis flushing": analysisFlushing,
  "analysis age": analysisAge,
  "analysis contaminant": analysisContaminant,
  "analysis sensor-placement kmeans": sensorKmeans,
  "analysis leakage identify": (ctx, argv) => schemeAnalysis(ctx, argv, "漏损识别执行成功", "/leakage-identifications", "scada_start", "scada_end"),
  "analysis leakage schemes list": (ctx) => schemeList(ctx, "读取漏损方案列表成功", "dma_leak_identification"),
  "analysis leakage schemes get": (ctx, argv) => schemeGet(ctx, argv, "读取漏损方案详情成功", "dma_leak_identification"),
  "analysis burst-detection detect": (ctx, argv) => schemeAnalysis(ctx, argv, "爆管检测执行成功", "/burst-detections", "scada_start", "scada_end"),
  "analysis burst-detection schemes list": (ctx) => schemeList(ctx, "读取爆管检测方案列表成功", "burst_detection"),
  "analysis burst-detection schemes get": (ctx, argv) => schemeGet(ctx, argv, "读取爆管检测方案详情成功", "burst_detection"),
  "analysis burst-location locate": burstLocation,
  "analysis burst-location schemes list": (ctx) => schemeList(ctx, "读取爆管定位方案列表成功", "burst_location"),
  "analysis burst-location schemes get": (ctx, argv) => schemeGet(ctx, argv, "读取爆管定位方案详情成功", "burst_location"),
  "analysis risk pipe-now": (ctx, argv) => riskPipe(ctx, argv, "读取当前管道风险成功", "/pipes/risk-probability-now"),
  "analysis risk pipe-history": (ctx, argv) => riskPipe(ctx, argv, "读取历史管道风险成功", "/pipes/risk-probability"),
  "analysis risk network": riskNetwork,
};
