import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

export const THREADS_MAX_CHARS = 500;

/** 避免素材特殊字元讓 provider API 在組 request JSON 時解析失敗 */
export function sanitizePromptText(text: string | null | undefined): string {
  if (!text) return "";
  return text
    .replace(/\r\n/g, "\n")
    .replace(/[\u2028\u2029]/g, "\n")
    .replace(/[\uD800-\uDFFF]/g, "")
    .replace(/\\(?!u[0-9a-fA-F]{4})/g, "＼")
    .replace(/\\u(?![0-9a-fA-F]{4})/g, "u")
    .replace(/\\/g, "＼")
    .replace(/\u0000/g, "");
}

/** 安全解析 fetch 回應，避免空 body 造成 JSON.parse 崩潰。 */
export async function parseFetchJson<T = Record<string, unknown>>(res: Response): Promise<T> {
  const text = await res.text();
  if (!text.trim()) {
    throw new Error(`伺服器回應為空（${res.status}）`);
  }
  try {
    return JSON.parse(text) as T;
  } catch {
    throw new Error(`伺服器回應格式錯誤（${res.status}）`);
  }
}

export function humanDelay(minMs = 800, maxMs = 2000): Promise<void> {
  const ms = Math.floor(Math.random() * (maxMs - minMs + 1)) + minMs;
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export function parseCount(text: string | null | undefined): number {
  if (!text) return 0;
  const cleaned = text.trim().toLowerCase().replace(/,/g, "");
  const match = cleaned.match(/([\d.]+)\s*([km萬]?)/);
  if (!match) return parseInt(cleaned, 10) || 0;
  const value = parseFloat(match[1]);
  const suffix = match[2];
  if (suffix === "k") return Math.round(value * 1000);
  if (suffix === "m") return Math.round(value * 1_000_000);
  if (suffix === "萬") return Math.round(value * 10_000);
  return Math.round(value);
}