"use client";

import React, { useEffect, useMemo, useState } from "react";
import {
  Box,
  Button,
  FormControl,
  MenuItem,
  Select,
  TextField,
  Typography,
} from "@mui/material";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import { DateTimePicker } from "@mui/x-date-pickers/DateTimePicker";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import { zhCN as pickerZhCN } from "@mui/x-date-pickers/locales";
import { useNotification } from "@refinedev/core";
import dayjs, { Dayjs } from "dayjs";
import "dayjs/locale/zh-cn";
import { api } from "@/lib/api";
import { NETWORK_NAME } from "@config/config";
import { useControllableObjectState } from "@components/olmap/core/useControllableState";
import { BurstDetectionResult } from "./types";

interface Props {
  onResult: (result: BurstDetectionResult) => void;
  state?: BurstDetectionAnalysisParametersState;
  onStateChange?: (state: BurstDetectionAnalysisParametersState) => void;
}

export interface BurstDetectionAnalysisParametersState {
  schemeName: string;
  detectionMode: "latest" | "historical";
  targetTime: Dayjs | null;
  samplingIntervalMinutes: number;
  samplingIntervalSource: "metadata" | "manual";
}

interface ScadaInfoItem {
  type?: string;
  transmission_frequency?: string | number | null;
}

const currentQuarterHour = () => {
  const now = dayjs().second(0).millisecond(0);
  return now.minute(Math.floor(now.minute() / 15) * 15);
};

export const createBurstDetectionAnalysisParametersState =
  (): BurstDetectionAnalysisParametersState => ({
    schemeName: `Burst_Detection_${Date.now()}`,
    detectionMode: "latest",
    targetTime: currentQuarterHour(),
    samplingIntervalMinutes: 15,
    samplingIntervalSource: "metadata",
  });

export const parseScadaFrequencyMinutes = (
  value: string | number | null | undefined,
): number | null => {
  if (typeof value === "number") {
    return Number.isInteger(value) && value > 0 ? value : null;
  }
  if (!value) return null;
  const normalized = value.trim();
  const dayMatch = normalized.match(/^(\d+)\s+days?,\s*(.+)$/i);
  const days = dayMatch ? Number(dayMatch[1]) : 0;
  const timePart = dayMatch ? dayMatch[2] : normalized;
  const parts = timePart.split(":").map(Number);
  if (parts.length !== 3 || parts.some((part) => !Number.isFinite(part))) {
    return null;
  }
  const minutes = days * 1440 + parts[0] * 60 + parts[1] + parts[2] / 60;
  return Number.isInteger(minutes) && minutes > 0 ? minutes : null;
};

export const resolvePressureSamplingInterval = (items: ScadaInfoItem[]) => {
  const counts = new Map<number, number>();
  items
    .filter((item) => item.type?.toLowerCase() === "pressure")
    .forEach((item) => {
      const minutes = parseScadaFrequencyMinutes(item.transmission_frequency);
      if (minutes && 1440 % minutes === 0) {
        counts.set(minutes, (counts.get(minutes) ?? 0) + 1);
      }
    });
  return [...counts.entries()].sort(
    ([minutesA, countA], [minutesB, countB]) =>
      countB - countA || minutesA - minutesB,
  )[0]?.[0] ?? 15;
};

export const buildBurstDetectionRequest = (
  parameters: BurstDetectionAnalysisParametersState,
) => ({
  scheme_name: parameters.schemeName.trim(),
  sampling_interval_minutes: parameters.samplingIntervalMinutes,
  ...(parameters.detectionMode === "historical" && parameters.targetTime
    ? { target_time: parameters.targetTime.toISOString() }
    : {}),
});

const AnalysisParameters: React.FC<Props> = ({
  onResult,
  state,
  onStateChange,
}) => {
  const { open } = useNotification();
  const [parametersState, setParametersState, setFormField] =
    useControllableObjectState(
      state,
      onStateChange,
      createBurstDetectionAnalysisParametersState(),
    );
  const {
    schemeName,
    detectionMode,
    targetTime,
    samplingIntervalMinutes,
    samplingIntervalSource,
  } = parametersState;
  const [running, setRunning] = useState(false);
  const [frequencyLoading, setFrequencyLoading] = useState(false);

  useEffect(() => {
    if (samplingIntervalSource !== "metadata") return;
    let active = true;
    setFrequencyLoading(true);
    api
      .get("/api/v1/scada-info")
      .then((response) => {
        if (!active) return;
        const interval = resolvePressureSamplingInterval(
          response.data as ScadaInfoItem[],
        );
        setParametersState((previous) =>
          previous.samplingIntervalSource === "metadata"
            ? { ...previous, samplingIntervalMinutes: interval }
            : previous,
        );
      })
      .catch(() => {
        // Keep the 15-minute fallback when SCADA metadata is unavailable.
      })
      .finally(() => {
        if (active) setFrequencyLoading(false);
      });
    return () => {
      active = false;
    };
  }, [samplingIntervalSource, setParametersState]);

  const samplingIntervalValid =
    Number.isInteger(samplingIntervalMinutes) &&
    samplingIntervalMinutes > 0 &&
    1440 % samplingIntervalMinutes === 0;

  const isValid = useMemo(
    () =>
      schemeName.trim().length > 0 &&
      samplingIntervalValid &&
      (detectionMode === "latest" || Boolean(targetTime?.isValid())),
    [detectionMode, samplingIntervalValid, schemeName, targetTime],
  );

  const handleRun = async () => {
    if (!isValid) {
      open?.({
        type: "error",
        message: "参数不完整",
        description: "请输入方案名称，并检查历史目标时间。",
      });
      return;
    }

    setRunning(true);
    open?.({
      key: "burst-detection-analysis-progress",
      type: "progress",
      message: "正在执行爆管侦测",
      description: "正在读取目标时刻及前 14 天同刻基线。",
      undoableTimeout: 3,
    });

    try {
      const response = await api.post(
        "/api/v1/burst-detections",
        buildBurstDetectionRequest(parametersState),
      );
      onResult(response.data as BurstDetectionResult);
      open?.({
        key: "burst-detection-analysis-success",
        type: "success",
        message: "爆管侦测完成",
        description: response.data.summary?.burst_detected
          ? "目标时刻存在异常信号，请优先复核相关测点。"
          : "目标时刻未发现爆管异常。",
      });
    } catch (error: any) {
      open?.({
        key: "burst-detection-analysis-error",
        type: "error",
        message: "侦测失败",
        description: error?.response?.data?.detail ?? error?.message ?? "请求失败",
      });
    } finally {
      setRunning(false);
    }
  };

  return (
    <Box className="flex min-h-0 flex-1 flex-col">
      <Box className="flex flex-col gap-3">
        <Box>
          <Typography variant="subtitle2" className="mb-1 font-medium">
            方案名称
          </Typography>
          <TextField
            value={schemeName}
            onChange={(event) => setFormField("schemeName", event.target.value)}
            placeholder="请输入方案名称"
            fullWidth
            size="small"
          />
        </Box>

        <Box>
          <Typography variant="subtitle2" className="mb-1 font-medium">
            侦测方式
          </Typography>
          <FormControl fullWidth size="small">
            <Select
              value={detectionMode}
              onChange={(event) =>
                setFormField(
                  "detectionMode",
                  event.target.value as "latest" | "historical",
                )
              }
            >
              <MenuItem value="latest">检测最新数据</MenuItem>
              <MenuItem value="historical">历史时刻回放</MenuItem>
            </Select>
          </FormControl>
        </Box>

        {detectionMode === "historical" ? (
          <LocalizationProvider
            dateAdapter={AdapterDayjs}
            adapterLocale="zh-cn"
            localeText={pickerZhCN.components.MuiLocalizationProvider.defaultProps.localeText}
          >
            <Box>
              <Typography variant="subtitle2" className="mb-1 font-medium">
                目标时刻
              </Typography>
              <DateTimePicker
                value={targetTime}
                onChange={(value) => setFormField("targetTime", value)}
                maxDateTime={dayjs()}
                minutesStep={15}
                format="YYYY-MM-DD HH:mm"
                slotProps={{ textField: { size: "small", fullWidth: true } }}
              />
            </Box>
          </LocalizationProvider>
        ) : null}

        <TextField
          type="number"
          label="采样间隔（分钟）"
          value={samplingIntervalMinutes}
          onChange={(event) => {
            setParametersState((previous) => ({
              ...previous,
              samplingIntervalMinutes: Number(event.target.value),
              samplingIntervalSource: "manual",
            }));
          }}
          size="small"
          fullWidth
          error={!samplingIntervalValid}
          inputProps={{ min: 1, max: 1440, step: 1 }}
          helperText={
            samplingIntervalValid
              ? `${frequencyLoading ? "正在读取 SCADA 频率" : samplingIntervalSource === "metadata" ? "默认取自压力 SCADA 频率" : "已手动设置"}，每天 ${1440 / samplingIntervalMinutes} 个采样点`
              : "请输入能整除 1440 分钟的正整数，例如 1、5、10、15、30 或 60。"
          }
        />

        {detectionMode === "latest" ? (
          <Box className="rounded-lg border border-blue-100 bg-blue-50 px-3 py-2 text-sm text-blue-900">
            系统自动读取目标时刻及前 14 天同一时刻数据。每天使用截至该时刻的
            24 小时压力序列提取扰动特征，仅判定目标时刻是否异常。
          </Box>
        ) : null}
        <Typography variant="caption" color="text.secondary">
          当前口径：{samplingIntervalMinutes || "-"} 分钟采样、
          {samplingIntervalValid ? 1440 / samplingIntervalMinutes : "-"} 点/天、14
          个参考日；缺失数据的测点不会插值，将从本次分析中排除。
        </Typography>
      </Box>

      <Box className="mt-auto flex gap-2 pt-3">
        <Button
          variant="outlined"
          fullWidth
          disabled={running}
          onClick={() =>
            setParametersState(createBurstDetectionAnalysisParametersState())
          }
        >
          重置
        </Button>
        <Button
          variant="contained"
          fullWidth
          disabled={!isValid || running}
          onClick={() => void handleRun()}
        >
          {running
            ? "侦测中..."
            : detectionMode === "latest"
              ? "侦测最新数据"
              : "回放目标时刻"}
        </Button>
      </Box>
    </Box>
  );
};

export default AnalysisParameters;
