import DateObject from "react-date-object";
import gregorian from "react-date-object/calendars/gregorian";
import gregorian_en from "react-date-object/locales/gregorian_en";
import persian from "react-date-object/calendars/persian";
import persian_fa from "react-date-object/locales/persian_fa";

export type DateRangePreset =
  | "today"
  | "yesterday"
  | "this-week"
  | "last-week"
  | "this-month"
  | "last-month"
  | "custom";

export const RANGE_OPTIONS: Array<[Exclude<DateRangePreset, "custom">, string]> = [
  ["today", "امروز"],
  ["yesterday", "دیروز"],
  ["this-week", "هفته جاری"],
  ["last-week", "هفته گذشته"],
  ["this-month", "ماه جاری"],
  ["last-month", "ماه گذشته"],
];

export function isRangePreset(value: string | null): value is DateRangePreset {
  return value === "custom" || RANGE_OPTIONS.some(([key]) => key === value);
}

export function rangeTitle(range: DateRangePreset): string {
  return RANGE_OPTIONS.find(([key]) => key === range)?.[1] ?? "بازه دلخواه";
}

function gregorianOf(iso: string): DateObject {
  return new DateObject({
    date: iso,
    format: "YYYY-MM-DD",
    calendar: gregorian,
    locale: gregorian_en,
  });
}

function jalaliOf(iso: string): DateObject {
  return gregorianOf(iso).convert(persian, persian_fa);
}

function isoOf(date: DateObject): string {
  return date.convert(gregorian, gregorian_en).format("YYYY-MM-DD");
}

/** «۲۷ مرداد ۱۴۰۵» */
export function faDate(iso: string): string {
  if (!iso) return "—";
  return jalaliOf(iso).format("D MMMM YYYY");
}

/** «۲۷ مرداد» — برای محورها و ردیف‌های فشرده. */
export function faDayMonth(iso: string): string {
  if (!iso) return "—";
  return jalaliOf(iso).format("D MMMM");
}

export function faWeekday(iso: string): string {
  if (!iso) return "—";
  return jalaliOf(iso).format("dddd");
}

export function shiftDays(iso: string, days: number): string {
  return isoOf(gregorianOf(iso).add(days, "day"));
}

/**
 * بازه هر پیش‌تنظیم روی تقویم جلالی حساب می‌شود تا «هفته» از شنبه و «ماه»
 * از اول ماه شمسی شروع شود؛ تاریخ مرجع (`today`) از سرور می‌آید.
 */
export function resolveRange(
  preset: DateRangePreset,
  today: string,
  custom: { from: string; to: string },
): { from: string; to: string } {
  if (preset === "custom") {
    return custom.from <= custom.to
      ? { from: custom.from, to: custom.to }
      : { from: custom.to, to: custom.from };
  }

  if (preset === "today") return { from: today, to: today };
  if (preset === "yesterday") {
    const yesterday = shiftDays(today, -1);
    return { from: yesterday, to: yesterday };
  }

  const base = jalaliOf(today);

  if (preset === "this-week") {
    return { from: isoOf(base.toFirstOfWeek()), to: today };
  }

  if (preset === "last-week") {
    const lastWeek = jalaliOf(today).subtract(7, "day");
    return {
      from: isoOf(lastWeek.toFirstOfWeek()),
      to: isoOf(jalaliOf(today).subtract(7, "day").toLastOfWeek()),
    };
  }

  if (preset === "this-month") {
    return { from: isoOf(base.toFirstOfMonth()), to: today };
  }

  const lastMonth = jalaliOf(today).toFirstOfMonth().subtract(1, "day");
  return {
    from: isoOf(jalaliOf(isoOf(lastMonth)).toFirstOfMonth()),
    to: isoOf(lastMonth),
  };
}

export function rangeLabel(
  preset: DateRangePreset,
  range: { from: string; to: string },
): string {
  if (range.from === range.to) {
    return preset === "today" ? `امروز · ${faDate(range.from)}` : faDate(range.from);
  }
  const prefix = preset === "custom" ? "" : `${rangeTitle(preset)} · `;
  return `${prefix}${faDate(range.from)} تا ${faDate(range.to)}`;
}
