/**
 * Jalali (Shamsi) date helpers for Design System.
 * Form/API values stay Gregorian ISO `YYYY-MM-DD`; UI is always Jalali.
 */
import { toJalaali, toGregorian, jalaaliMonthLength as jMonthLength } from "jalaali-js";

export const WEEKDAYS = ["ش", "ی", "د", "س", "چ", "پ", "ج"] as const;

export const MONTHS = [
  "فروردین",
  "اردیبهشت",
  "خرداد",
  "تیر",
  "مرداد",
  "شهریور",
  "مهر",
  "آبان",
  "آذر",
  "دی",
  "بهمن",
  "اسفند",
] as const;

export type JalaliParts = { year: number; month: number; day: number };

function pad(n: number) {
  return String(n).padStart(2, "0");
}

function parseIso(iso: string): { gy: number; gm: number; gd: number } | null {
  const m = iso.trim().match(/^(\d{4})-(\d{2})-(\d{2})/);
  if (!m) return null;
  return { gy: Number(m[1]), gm: Number(m[2]), gd: Number(m[3]) };
}

/** Today as Gregorian ISO date for API defaults. */
export function todayIso(): string {
  const now = new Date();
  return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
}

export function isoToJalaliParts(iso?: string | null): JalaliParts {
  const parsed = iso ? parseIso(iso) : null;
  const d = parsed
    ? new Date(parsed.gy, parsed.gm - 1, parsed.gd)
    : new Date();
  const j = toJalaali(d.getFullYear(), d.getMonth() + 1, d.getDate());
  return { year: j.jy, month: j.jm, day: j.jd };
}

export function jalaliPartsToIso(parts: JalaliParts): string {
  const g = toGregorian(parts.year, parts.month, parts.day);
  return `${g.gy}-${pad(g.gm)}-${pad(g.gd)}`;
}

/** Format Gregorian ISO as Jalali `YYYY/MM/DD`. */
export function formatJalali(value?: string | Date | null): string {
  if (value === null || value === undefined || value === "") return "—";
  let gy: number;
  let gm: number;
  let gd: number;
  if (value instanceof Date) {
    gy = value.getFullYear();
    gm = value.getMonth() + 1;
    gd = value.getDate();
  } else {
    const parsed = parseIso(String(value));
    if (parsed) {
      gy = parsed.gy;
      gm = parsed.gm;
      gd = parsed.gd;
    } else {
      const d = new Date(String(value));
      if (Number.isNaN(d.getTime())) return String(value);
      gy = d.getFullYear();
      gm = d.getMonth() + 1;
      gd = d.getDate();
    }
  }
  const j = toJalaali(gy, gm, gd);
  return `${j.jy}/${pad(j.jm)}/${pad(j.jd)}`;
}

/** Jalali date + local time for audit timestamps. */
export function formatJalaliDateTime(value?: string | Date | null): string {
  if (value === null || value === undefined || value === "") return "—";
  const d = value instanceof Date ? value : new Date(String(value));
  if (Number.isNaN(d.getTime())) return String(value);
  return `${formatJalali(d)} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
}

export function jalaliMonthLength(year: number, month: number): number {
  return jMonthLength(year, month);
}

/** Weekday index Sat=0 … Fri=6 for Jalali calendar grid. */
export function jalaliWeekdaySat0(year: number, month: number, day: number): number {
  const g = toGregorian(year, month, day);
  const jsDay = new Date(g.gy, g.gm - 1, g.gd).getDay(); // 0=Sun
  return (jsDay + 1) % 7;
}

export function shiftJalaliMonth(
  year: number,
  month: number,
  delta: number
): { year: number; month: number } {
  let m = month + delta;
  let y = year;
  while (m < 1) {
    m += 12;
    y -= 1;
  }
  while (m > 12) {
    m -= 12;
    y += 1;
  }
  return { year: y, month: m };
}
