export function asRecord(value: unknown): Record<string, unknown> | null {
  return value && typeof value === "object" ? value as Record<string, unknown> : null;
}

export function nonEmptyString(value: unknown): string | null {
  if (typeof value !== "string") return null;
  const text = value.trim();
  return text ? text : null;
}

export function firstNonEmptyString(...values: unknown[]): string | null {
  for (const value of values) {
    const text = nonEmptyString(value);
    if (text) return text;
  }
  return null;
}

export function normalizeWorkbenchConversationId(value: unknown): string | null {
  const text = nonEmptyString(value);
  if (!text) return null;
  return /^cnv_[A-Za-z0-9_.:-]+$/u.test(text) ? text : null;
}

export function normalizeWorkbenchSessionId(value: unknown): string | null {
  const text = nonEmptyString(value);
  if (!text) return null;
  return /^ses_[A-Za-z0-9_.:-]+$/u.test(text) ? text : null;
}

export function normalizeWorkbenchSessionRouteId(value: unknown): string | null {
  const text = nonEmptyString(value);
  if (!text) return null;
  return normalizeWorkbenchSessionId(text) ?? normalizeWorkbenchConversationId(text);
}

export function workbenchSessionPath(sessionId: string): string {
  return `/workbench/sessions/${encodeURIComponent(sessionId)}`;
}

export function nextProtocolId(prefix: string): string {
  const cryptoApi = typeof crypto !== "undefined" ? crypto : null;
  const suffix = cryptoApi?.randomUUID ? cryptoApi.randomUUID().replace(/-/gu, "").slice(0, 16) : `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;
  return `${prefix}_${suffix}`;
}

export function statusTone(status: string | undefined | null): string {
  const text = String(status ?? "").toLowerCase();
  if (["completed", "ok", "healthy", "ready", "active"].includes(text)) return "ok";
  if (["running", "accepted", "pending", "processing"].includes(text)) return "pending";
  if (["warn", "warning", "degraded", "build_time_unavailable"].includes(text)) return "warn";
  if (["blocked", "stale"].includes(text)) return "blocked";
  if (["failed", "error", "timeout", "canceled", "cancelled"].includes(text)) return "error";
  return "pending";
}

export function formatRelativeTime(value: string | null | undefined): string {
  if (!value) return "未记录";
  const date = new Date(value);
  if (!Number.isFinite(date.getTime())) return value;
  const delta = Date.now() - date.getTime();
  if (delta < 60_000) return "刚刚";
  if (delta < 3_600_000) return `${Math.round(delta / 60_000)} 分钟前`;
  if (delta < 86_400_000) return `${Math.round(delta / 3_600_000)} 小时前`;
  return date.toLocaleString();
}
