const CUSTOM_DATE_RANGES_KEY = "custom_date_ranges_v1";
const CUSTOM_DATE_RANGE_EVENT = "teaGangCustomDateRangesChanged";

const WEEKDAYS = [
  { value: 1, label: "Monday" },
  { value: 2, label: "Tuesday" },
  { value: 3, label: "Wednesday" },
  { value: 4, label: "Thursday" },
  { value: 5, label: "Friday" },
  { value: 6, label: "Saturday" },
  { value: 7, label: "Sunday" },
];

const DEFAULT_CUSTOM_DATE_RANGES = [
  {
    id: "sale_week",
    name: "Sale week",
    startWeekday: 7,
    endWeekday: 6,
  },
];

const normalizeCustomDateRanges = (ranges) => {
  if (typeof ranges === "string") {
    try {
      return normalizeCustomDateRanges(JSON.parse(ranges));
    } catch (_) {
      return [];
    }
  }
  if (!Array.isArray(ranges)) return [];
  return ranges
    .map((range) => ({
      id: String(range?.id || "").trim(),
      name: String(range?.name || "").trim(),
      startWeekday: Number(range?.startWeekday || 1),
      endWeekday: Number(range?.endWeekday || 1),
    }))
    .filter((range) =>
      range.id &&
      range.name &&
      range.startWeekday >= 1 &&
      range.startWeekday <= 7 &&
      range.endWeekday >= 1 &&
      range.endWeekday <= 7
    );
};

const readWebPreferencesLocal = () => {
  try {
    return JSON.parse(window.localStorage.getItem("teaGangWebPreferences") || "{}");
  } catch (_) {
    return {};
  }
};

const readCustomDateRangesLocal = () => {
  const ranges = normalizeCustomDateRanges(readWebPreferencesLocal()[CUSTOM_DATE_RANGES_KEY]);
  return ranges.length ? ranges : DEFAULT_CUSTOM_DATE_RANGES;
};

const loadCustomDateRangesForWeb = async () => {
  const backend = window.TeaGangBackend;
  if (backend?.enabled && backend.fetchCustomDateRanges) {
    try {
      const ranges = await backend.fetchCustomDateRanges();
      return ranges.length ? ranges : DEFAULT_CUSTOM_DATE_RANGES;
    } catch (error) {
      console.warn("Could not load custom date ranges.", error);
    }
  }
  if (backend?.enabled && backend.fetchUserPreferences) {
    try {
      const remote = await backend.fetchUserPreferences("web");
      if (remote && CUSTOM_DATE_RANGES_KEY in remote) {
        const ranges = normalizeCustomDateRanges(remote[CUSTOM_DATE_RANGES_KEY]);
        return ranges.length ? ranges : DEFAULT_CUSTOM_DATE_RANGES;
      }
    } catch (error) {
      console.warn("Could not load custom date ranges.", error);
    }
  }
  return readCustomDateRangesLocal();
};

const weekdayLabel = (weekday) =>
  WEEKDAYS.find((day) => day.value === Number(weekday))?.label || "Monday";

const customRangeLabel = (range) =>
  `${weekdayLabel(range.startWeekday)} - ${weekdayLabel(range.endWeekday)}`;

const customRangeFilterId = (range) => `custom-range:${range.id}`;

const rangeFromCustomWeekdays = (range, anchor = new Date()) => {
  const today = new Date(anchor.getFullYear(), anchor.getMonth(), anchor.getDate());
  const todayWeekday = today.getDay() || 7;
  const startWeekday = Number(range.startWeekday) || 1;
  const endWeekday = Number(range.endWeekday) || 1;
  const daysSinceStart = (todayWeekday - startWeekday + 7) % 7;
  const rangeLength = (endWeekday - startWeekday + 7) % 7;
  const start = new Date(today);
  start.setDate(today.getDate() - daysSinceStart);
  const endExclusive = new Date(start);
  endExclusive.setDate(start.getDate() + rangeLength + 1);
  return { dateFrom: start, dateTo: endExclusive };
};

const findCustomRangeByFilter = (ranges, filter) => {
  if (!String(filter || "").startsWith("custom-range:")) return null;
  const id = String(filter).slice("custom-range:".length);
  return normalizeCustomDateRanges(ranges).find((range) => range.id === id) || null;
};

const notifyCustomDateRangesChanged = () => {
  window.dispatchEvent(new CustomEvent(CUSTOM_DATE_RANGE_EVENT));
};

window.TeaGangCustomDateRanges = {
  key: CUSTOM_DATE_RANGES_KEY,
  event: CUSTOM_DATE_RANGE_EVENT,
  weekdays: WEEKDAYS,
  defaults: DEFAULT_CUSTOM_DATE_RANGES,
  normalize: normalizeCustomDateRanges,
  readLocal: readCustomDateRangesLocal,
  load: loadCustomDateRangesForWeb,
  label: customRangeLabel,
  filterId: customRangeFilterId,
  range: rangeFromCustomWeekdays,
  findByFilter: findCustomRangeByFilter,
  notifyChanged: notifyCustomDateRangesChanged,
};
