export const BEIJING_TIME_ZONE = "Asia/Shanghai";
export const BEIJING_TIME_LABEL = "北京时间";

const BEIJING_UTC_OFFSET_HOURS = 8;
const DATE_TIME_OPTIONS: Intl.DateTimeFormatOptions = {
  timeZone: BEIJING_TIME_ZONE,
  hour12: false,
};
const CLOCK_OPTIONS: Intl.DateTimeFormatOptions = {
  timeZone: BEIJING_TIME_ZONE,
  hour12: false,
};
const INPUT_PARTS_FORMATTER = new Intl.DateTimeFormat("en-CA", {
  timeZone: BEIJING_TIME_ZONE,
  year: "numeric",
  month: "2-digit",
  day: "2-digit",
  hour: "2-digit",
  minute: "2-digit",
  hourCycle: "h23",
});

function coerceDate(value: any): Date | null {
  if (value === null || value === undefined || value === "") return null;
  const date = value instanceof Date ? value : new Date(value);
  return Number.isNaN(date.getTime()) ? null : date;
}

function beijingInputParts(value: any): Record<string, string> | null {
  const date = coerceDate(value);
  if (!date) return null;
  return INPUT_PARTS_FORMATTER.formatToParts(date).reduce((parts: Record<string, string>, part) => {
    if (part.type !== "literal") parts[part.type] = part.value;
    return parts;
  }, {});
}

export function fmtDate(value: any): string {
  const date = coerceDate(value);
  return date ? date.toLocaleString("zh-CN", DATE_TIME_OPTIONS) : "--";
}

export function fmtClock(value: any): string {
  const date = coerceDate(value);
  return date ? date.toLocaleTimeString("zh-CN", CLOCK_OPTIONS) : "--";
}

export function fmtDateTimeLocalInput(value: any): string {
  const parts = beijingInputParts(value);
  if (!parts) return "";
  const hour = parts.hour === "24" ? "00" : parts.hour;
  return `${parts.year}-${parts.month}-${parts.day}T${hour}:${parts.minute}`;
}

export function beijingDateStamp(value: any = new Date()): string {
  const parts = beijingInputParts(value);
  if (!parts) return "";
  return `${parts.year}-${parts.month}-${parts.day}`;
}

export function localDateTimeInputToBeijingIso(value: string): string | null {
  if (!value) return null;
  const match = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?$/.exec(value);
  if (!match) return null;
  const [, year, month, day, hour, minute, second = "00"] = match;
  const utcMs = Date.UTC(
    Number(year),
    Number(month) - 1,
    Number(day),
    Number(hour) - BEIJING_UTC_OFFSET_HOURS,
    Number(minute),
    Number(second),
  );
  const date = new Date(utcMs);
  const normalized = fmtDateTimeLocalInput(date);
  return Number.isNaN(date.getTime()) || normalized !== `${year}-${month}-${day}T${hour}:${minute}` ? null : date.toISOString();
}
