import type { AdminApiLocale } from "@/lib/admin-locale";

function formatParts(date: Date, timeZone?: string): string {
  const parts = new Intl.DateTimeFormat("en-CA", {
    timeZone,
    year: "numeric",
    month: "2-digit",
    day: "2-digit",
    hour: "2-digit",
    minute: "2-digit",
    second: "2-digit",
    hourCycle: "h23",
  }).formatToParts(date);

  const map = new Map(parts.map((part) => [part.type, part.value]));
  const year = map.get("year") ?? "0000";
  const month = map.get("month") ?? "00";
  const day = map.get("day") ?? "00";
  const hour = map.get("hour") ?? "00";
  const minute = map.get("minute") ?? "00";
  const second = map.get("second") ?? "00";

  return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
}

const WEEKDAY_KEYS = [
  "sunday",
  "monday",
  "tuesday",
  "wednesday",
  "thursday",
  "friday",
  "saturday",
] as const;

export type AdminWeekdayKey = (typeof WEEKDAY_KEYS)[number];

export function adminWeekdayKeyForDate(date: Date = new Date()): AdminWeekdayKey {
  return WEEKDAY_KEYS[date.getDay()] ?? "sunday";
}

/**
 * 仪表盘顶栏日期：数字日期 + i18n 星期（避免 Intl 在 ne 等语言下回退到系统中文）。
 */
export function formatAdminCalendarToday(locale: AdminApiLocale, weekdayLabel: string): string {
  const d = new Date();
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, "0");
  const day = String(d.getDate()).padStart(2, "0");
  const datePart = locale === "en" ? `${m}/${day}/${y}` : `${y}-${m}-${day}`;

  return `${datePart} ${weekdayLabel}`;
}

/** 与后端 `now()->toDateString()` 对齐的业务日（本地日历日 YYYY-MM-DD）。 */
export function formatAdminBusinessDateIso(date: Date = new Date()): string {
  const y = date.getFullYear();
  const m = String(date.getMonth() + 1).padStart(2, "0");
  const day = String(date.getDate()).padStart(2, "0");

  return `${y}-${m}-${day}`;
}

const NAIVE_SCHEDULE_CLOCK_RE =
  /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/;

/** 浏览器本地时区短标签（如 CST、GMT+8），用于界面说明。 */
export function getAdminBrowserTimeZoneLabel(date = new Date()): string {
  try {
    const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
    const parts = new Intl.DateTimeFormat(undefined, {
      timeZone,
      timeZoneName: "short",
    }).formatToParts(date);
    return parts.find((part) => part.type === "timeZoneName")?.value ?? timeZone;
  } catch {
    return "Local";
  }
}

/**
 * 将接口 ISO 8601 时间转为本地时区的 `YYYY-MM-DD HH:mm:ss`（表单预填、期号展示）。
 */
export function isoToAdminLocalScheduleValue(
  iso: string | null | undefined,
): string {
  if (iso == null || iso === "") {
    return "";
  }
  const ms = Date.parse(iso);
  if (Number.isNaN(ms)) {
    return "";
  }
  return formatParts(new Date(ms));
}

/**
 * 将本地时区下的计划时刻转为指定排期时区（默认 UTC）的 naive `YYYY-MM-DD HH:mm:ss`，供创建/编辑期号 API。
 */
export function adminLocalScheduleValueToTimezoneNaive(
  clock: string,
  scheduleTimezone = "UTC",
): string {
  const trimmed = clock.trim();
  if (trimmed === "") {
    return "";
  }
  const match = NAIVE_SCHEDULE_CLOCK_RE.exec(trimmed);
  if (!match) {
    return trimmed;
  }
  const [, y, mo, d, h, mi, s] = match;
  const localMs = new Date(
    Number(y),
    Number(mo) - 1,
    Number(d),
    Number(h),
    Number(mi),
    Number(s),
  ).getTime();
  if (Number.isNaN(localMs)) {
    return trimmed;
  }
  try {
    return formatParts(new Date(localMs), scheduleTimezone);
  } catch {
    return trimmed;
  }
}

/**
 * 将接口返回的 ISO 时间串格式化为浏览器本地时区下的 `YYYY-MM-DD HH:mm:ss`。
 */
export function formatAdminInstant(
  iso: string | null | undefined,
  options: {
    locale: AdminApiLocale;
  },
): string {
  void options;
  if (iso == null || iso === "") {
    return "—";
  }
  const ms = Date.parse(iso);
  if (Number.isNaN(ms)) {
    return "—";
  }
  return formatParts(new Date(ms));
}

/**
 * 将接口返回的 ISO 时间串格式化到指定时区，便于并列展示多个地区的时间。
 */
export function formatAdminInstantInTimeZone(
  iso: string | null | undefined,
  options: {
    locale: AdminApiLocale;
    timeZone: string;
  },
): string {
  void options.locale;
  if (iso == null || iso === "") {
    return "—";
  }
  const ms = Date.parse(iso);
  if (Number.isNaN(ms)) {
    return "—";
  }
  try {
    return formatParts(new Date(ms), options.timeZone);
  } catch {
    return formatParts(new Date(ms));
  }
}
