import { useMemoizedFn } from "ahooks";
import { trim } from "lodash-es";
import prettyMs from "pretty-ms";
import { useMemo } from "react";
import { dayjs } from "../../utils/dayjs.mjs";
const DEFAULT_QUICK_RANGES = [
  5 * 60,
  15 * 60,
  30 * 60,
  60 * 60,
  3 * 60 * 60,
  12 * 60 * 60,
  24 * 60 * 60,
  2 * 24 * 60 * 60,
  3 * 24 * 60 * 60
];
const DEFAULT_TIME_RANGE = {
  type: "relative",
  value: 30 * 60
};
const formatDuration = (seconds, short = false) => {
  if (short) {
    return prettyMs(seconds * 1e3, { compact: true });
  } else {
    return prettyMs(seconds * 1e3, { verbose: true });
  }
};
const toTimeRangeValue = (timeRange, offset = 0) => {
  if (timeRange.type === "absolute") {
    return timeRange.value.map((t) => t + offset);
  } else {
    let now = dayjs().unix();
    if (timeRange.utcOffset) {
      now = dayjs(convertToLocal(dayjs().toDate(), timeRange.utcOffset)).unix();
    }
    return timeRange.isFuture ? [now + offset, now + timeRange.value + offset] : [now - timeRange.value + offset, now + offset];
  }
};
function fromTimeRangeValue(v) {
  return {
    type: "absolute",
    value: [...v]
  };
}
const toURLTimeRange = (timeRange) => {
  if (timeRange.type === "relative") {
    const isFuture = timeRange.isFuture;
    return isFuture ? { from: "now", to: `${timeRange.value}` } : { from: `${timeRange.value}`, to: "now" };
  }
  const timeRangeValue = toTimeRangeValue(timeRange);
  return { from: `${timeRangeValue[0]}`, to: `${timeRangeValue[1]}` };
};
const urlToTimeRange = (urlTimeRange) => {
  if (urlTimeRange.to === "now" || urlTimeRange.from === "now") {
    return { type: "relative", value: Number(urlTimeRange.from), isFuture: urlTimeRange.from === "now" };
  }
  return { type: "absolute", value: [Number(urlTimeRange.from), Number(urlTimeRange.to)] };
};
const urlToTimeRangeValue = (urlTimeRange) => {
  return toTimeRangeValue(urlToTimeRange(urlTimeRange));
};
const DEFAULT_TIME_FORMAT = "YYYY-MM-DD HH:mm:ss";
const DEFAULT_TIME_FORMAT_WITH_TIMEZONE = "YYYY-MM-DD HH:mm:ss Z";
function addOffsetUTC(time, utcOffset) {
  const targetTime = new Date(time);
  const tzDifference = utcOffset * 60 + targetTime.getTimezoneOffset();
  return new Date(targetTime.getTime() + tzDifference * 60 * 1e3);
}
const getUTCString = (offset) => {
  const offsetStrs = offset.toString().split(".");
  let mm = "00";
  let hh = "";
  const offsetH = Number.parseInt(offsetStrs[0] || "0");
  const offsetM = Number.parseFloat(`0.${offsetStrs[1]}` || "0") * 60;
  hh = Math.abs(offsetH).toString().padStart(2, "0");
  mm = offsetM === 0 ? "00" : offsetM.toString();
  if (offset > 0) {
    return `UTC+${hh}:${mm}`;
  }
  if (offset < 0) {
    return `UTC-${hh}:${mm}`;
  }
  return "UTC±00:00";
};
const timeFormatter = (timeValue, utcOffset, format = DEFAULT_TIME_FORMAT) => {
  if (!timeValue) return "-";
  const time = timeValue instanceof Date || isNaN(Number(timeValue)) ? timeValue : Number(timeValue) * 1e3;
  const currentTZOffsetInHours = utcOffset === void 0 || utcOffset === null ? -((/* @__PURE__ */ new Date()).getTimezoneOffset() / 60) : utcOffset;
  const withUTC = format.indexOf("Z") >= 0;
  return dayjs(addOffsetUTC(time, currentTZOffsetInHours)).format(withUTC ? trim(format, "Z") : format) + (withUTC ? getUTCString(currentTZOffsetInHours) : "");
};
const convertToLocal = (date, utcOffset) => {
  const targetTime = dayjs(date).utcOffset(utcOffset);
  const converted = targetTime.utcOffset(dayjs().utcOffset(), true);
  return new Date(converted.format());
};
const useTimeRangePicker = ({
  value,
  onChange,
  minDateTime,
  maxDateTime,
  maxDuration,
  relativeFormatter,
  absoluteFormatter,
  dateInputFormat,
  utcOffset = dayjs().utcOffset()
}) => {
  const convertFromLocal = useMemoizedFn((date) => {
    const targetTime = dayjs(date).utcOffset(utcOffset, true);
    return new Date(targetTime.format());
  });
  const convertAbsoluteTimeRangeToLocal = useMemoizedFn((timeRange) => {
    const [from, to] = timeRange.value;
    const fromDate = new Date(from * 1e3);
    const toDate = new Date(to * 1e3);
    const localFromDate = convertToLocal(fromDate, utcOffset);
    const localToDate = convertToLocal(toDate, utcOffset);
    return {
      type: "absolute",
      value: [Math.floor(localFromDate.getTime() / 1e3), Math.floor(localToDate.getTime() / 1e3)]
    };
  });
  const convertAbsoluteTimeRangeFromLocal = useMemoizedFn((timeRange) => {
    const [from, to] = timeRange.value;
    const fromDate = new Date(from * 1e3);
    const toDate = new Date(to * 1e3);
    const targetFromDate = convertFromLocal(fromDate);
    const targetToDate = convertFromLocal(toDate);
    return {
      type: "absolute",
      value: [Math.floor(targetFromDate.getTime() / 1e3), Math.floor(targetToDate.getTime() / 1e3)]
    };
  });
  const displayValue = useMemo(() => {
    if (value.type === "relative") {
      const _v = { ...value };
      _v.utcOffset = utcOffset;
      return _v;
    }
    return convertAbsoluteTimeRangeToLocal(value);
  }, [value, convertAbsoluteTimeRangeToLocal]);
  const displayMinDateTime = useMemo(() => {
    if (!minDateTime) return void 0;
    return () => convertToLocal(minDateTime(), utcOffset);
  }, [minDateTime]);
  const displayMaxDateTime = useMemo(() => {
    if (!maxDateTime) return void 0;
    return () => convertToLocal(maxDateTime(), utcOffset);
  }, [maxDateTime]);
  const handleChange = useMemoizedFn((localTimeRange) => {
    if (!localTimeRange) {
      onChange == null ? void 0 : onChange(void 0);
      return;
    }
    if (localTimeRange.type === "relative") {
      onChange == null ? void 0 : onChange(localTimeRange);
      return;
    }
    const targetTimeRange = convertAbsoluteTimeRangeFromLocal(localTimeRange);
    onChange == null ? void 0 : onChange(targetTimeRange);
  });
  const displayRelativeFormatter = useMemo(() => {
    if (!relativeFormatter) return void 0;
    return (relativeRange) => relativeFormatter(relativeRange);
  }, [relativeFormatter]);
  const displayAbsoluteFormatter = useMemo(() => {
    if (!absoluteFormatter) return void 0;
    return (absoluteRange) => {
      const targetRange = convertAbsoluteTimeRangeFromLocal(absoluteRange);
      return absoluteFormatter(targetRange);
    };
  }, [absoluteFormatter, convertAbsoluteTimeRangeFromLocal]);
  const displayDateInputFormat = useMemo(() => {
    if (!dateInputFormat) return void 0;
    return (date) => {
      const targetDate = convertFromLocal(date);
      return dateInputFormat(targetDate);
    };
  }, [dateInputFormat, convertFromLocal]);
  return {
    value: displayValue,
    onChange: handleChange,
    minDateTime: displayMinDateTime,
    maxDateTime: displayMaxDateTime,
    maxDuration,
    relativeFormatter: displayRelativeFormatter,
    absoluteFormatter: displayAbsoluteFormatter,
    dateInputFormat: displayDateInputFormat,
    timezone: typeof utcOffset === "number" ? utcOffset : void 0
  };
};
export {
  DEFAULT_QUICK_RANGES,
  DEFAULT_TIME_FORMAT,
  DEFAULT_TIME_FORMAT_WITH_TIMEZONE,
  DEFAULT_TIME_RANGE,
  addOffsetUTC,
  formatDuration,
  fromTimeRangeValue,
  getUTCString,
  timeFormatter,
  toTimeRangeValue,
  toURLTimeRange,
  urlToTimeRange,
  urlToTimeRangeValue,
  useTimeRangePicker
};
