import dayjs from 'dayjs';
import customParseFormat from 'dayjs/plugin/customParseFormat';
import UTC from 'dayjs/plugin/utc';
import _ from 'lodash';

dayjs.extend(UTC);
dayjs.extend(customParseFormat);
const DEFAULT_TIME = dayjs("00:00", "HH:mm");
function getTime(cronTime, isUTC = false) {
  const { hour, minute } = cronTime.unitMap;
  const _hour = Object.keys(hour)[0];
  const _minute = Object.keys(minute)[0];
  if (isUTC) {
    return dayjs.utc(`${_hour}:${_minute}`, "HH:mm").local();
  }
  return dayjs(`${_hour}:${_minute}`, "HH:mm");
}
function getMode(source) {
  if (source.startsWith("@x-every-n-day")) {
    return "day";
  }
  if (source.startsWith("@x-every-n-week")) {
    return "week";
  }
  const [, , , monthDay, month] = source.split(" ");
  if (!monthDay || !month) {
    return "day";
  }
  if (!monthDay.includes("*") || month !== "*") {
    return "month";
  }
  return "day";
}
function getDaily(mode, source, time, defaultTime = DEFAULT_TIME) {
  const matchedArr = source.match(/@x-every-n-day\(\d+,\d+,(\d+)\)/);
  const step = matchedArr ? parseInt(matchedArr[1], 10) : 1;
  return {
    step,
    time: mode === "day" ? time : defaultTime
  };
}
function toDailyString(step, time) {
  return `@x-every-n-day(${time.minute()},${time.hour()},${step || 1})`;
}
function getWeekly(mode, source, time, defaultTime = DEFAULT_TIME) {
  const matchedArr = source.match(/@x-every-n-week\(\d+,\d+,(\d+),(.+)\)/);
  const step = matchedArr ? parseInt(matchedArr[1], 10) : 1;
  const days = matchedArr ? matchedArr[2] === "*" ? [] : matchedArr[2].split(",").map((v) => parseInt(v, 10)) : [];
  return {
    step,
    days,
    time: mode === "week" ? time : defaultTime
  };
}
function toWeeklyString(step, time, days) {
  return `@x-every-n-week(${time.minute()},${time.hour()},${step || 1},${days.join(",") || "*"})`;
}
function getMonthly(mode, month, day, time, defaultTime = DEFAULT_TIME) {
  return {
    step: month === "*" ? 1 : parseInt(_.last(month) || "1", 10),
    days: day === "*" || mode !== "month" || !month ? [] : day.split(",").map((v) => parseInt(v, 10)),
    time: mode === "month" ? time : defaultTime
  };
}
function toMonthlyString(step, time, days) {
  return [
    0,
    time.minute(),
    time.hour(),
    days.join(",") || "*",
    step > 1 ? `*/${step}` : "*",
    "*"
  ].join(" ");
}

export { DEFAULT_TIME, getDaily, getMode, getMonthly, getTime, getWeekly, toDailyString, toMonthlyString, toWeeklyString };
