/**
 * Shared formatting utilities — DRY extraction from duplicated functions
 * across RequestLoggerV2.js, UsageAnalytics.js, ProxyLogger.js
 *
 * Prevents copy-paste duplication and provides a single source of truth.
 */

import { maskEmail } from "./maskEmail";

/**
 * Format an ISO date string to a localized time string (HH:MM:SS).
 * @param {string} isoString - ISO 8601 date string
 * @returns {string}
 */
export function formatTime(isoString: string | null | undefined) {
  try {
    if (!isoString) return "-";
    const d = new Date(isoString);
    return d.toLocaleTimeString("en-US", {
      hour12: false,
      hour: "2-digit",
      minute: "2-digit",
      second: "2-digit",
    });
  } catch {
    return "-";
  }
}

/**
 * Format a duration in milliseconds to a human-readable string.
 * @param {number} ms - Duration in milliseconds
 * @returns {string} e.g., "42ms", "1.2s", "-"
 */
export function formatDuration(ms: number | null | undefined) {
  if (!ms) return "-";
  if (ms < 1000) return `${ms}ms`;
  return `${(ms / 1000).toFixed(1)}s`;
}

/**
 * Format an ISO date to a full date+time string (pt-BR locale).
 * @param {string} iso - ISO 8601 date string
 * @returns {string}
 */
export function formatDateTime(iso: string | null | undefined) {
  try {
    if (!iso) return "-";
    const d = new Date(iso);
    return d.toLocaleDateString("pt-BR") + ", " + d.toLocaleTimeString("en-US", { hour12: false });
  } catch {
    return iso;
  }
}

/**
 * Mask a string by showing only start and end characters.
 * @param {string} value - Value to mask
 * @param {number} start - Number of characters to show at start (default: 2)
 * @param {number} end - Number of characters to show at end (default: 2)
 * @returns {string}
 */
export function maskSegment(value: string | null | undefined, start = 2, end = 2) {
  if (!value) return "";
  if (value.length <= start + end) return `${value.slice(0, 1)}***`;
  return `${value.slice(0, start)}***${value.slice(-end)}`;
}

/**
 * Mask an email or account string for display.
 * @param {string} account - Account identifier (email or username)
 * @param {boolean} emailsVisible - Whether to show full email (true) or mask it (false)
 * @returns {string}
 */
export function maskAccount(account: string | null | undefined, emailsVisible: boolean) {
  if (!account || account === "-") return "-";
  if (emailsVisible) return account;
  const atIdx = account.indexOf("@");
  if (atIdx > 3) {
    return maskEmail(account);
  }
  if (account.length > 8) {
    return account.slice(0, 5) + "***";
  }
  return account;
}

export function stableAccountSuffix(account: string | null | undefined): string {
  if (!account || account === "-") return "0000";
  let hash = 0x811c9dc5;
  for (let i = 0; i < account.length; i++) {
    hash ^= account.charCodeAt(i);
    hash = Math.imul(hash, 0x01000193) >>> 0;
  }
  return hash.toString(16).padStart(8, "0").slice(0, 4);
}

/**
 * Format an API key label, showing full name but masking the ID.
 * @param {string} apiKeyName - Human-readable name of the key
 * @param {string} apiKeyId - Unique ID of the key
 * @returns {string}
 */
export function formatApiKeyLabel(
  apiKeyName: string | null | undefined,
  apiKeyId: string | null | undefined
) {
  if (!apiKeyName && !apiKeyId) return "—";
  const displayName = apiKeyName || "key";
  if (!apiKeyId) return displayName;
  return `${displayName} (${maskSegment(apiKeyId, 4, 4)})`;
}

/**
 * Mask a sensitive key for log output.
 * @param {string} key - API key or token to mask
 * @returns {string}
 */
export function maskKey(key: string | null | undefined) {
  if (!key || key.length < 8) return "***";
  return `${key.slice(0, 4)}...${key.slice(-4)}`;
}

/**
 * Format large numbers with K/M/B suffixes.
 * @param {number} n - Number to format
 * @returns {string}
 */
export function fmtCompact(n: number | null | undefined) {
  if (n && n >= 1_000_000_000) return `${(n / 1_000_000_000).toFixed(1)}B`;
  if (n && n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;
  if (n && n >= 1_000) return `${(n / 1_000).toFixed(1)}K`;
  return new Intl.NumberFormat().format(n || 0);
}

/**
 * Format a number with full locale formatting.
 * @param {number} n - Number to format
 * @returns {string}
 */
export function fmtFull(n: number | null | undefined) {
  return new Intl.NumberFormat().format(n || 0);
}

/**
 * Format a USD cost for display.
 * Sub-cent values show additional precision.
 * @param {number} usd - Cost in USD
 * @returns {string}
 */
export function formatCost(usd: number | null | undefined): string {
  const value = Number(usd || 0);
  if (!Number.isFinite(value) || value === 0) return "$0.00";
  if (value < 0.01) return `$${value.toFixed(6)}`;
  if (value < 1) return `$${value.toFixed(4)}`;
  return `$${value.toFixed(2)}`;
}

export const fmtCost = formatCost;

/**
 * Format a USD cost for display using abbreviated K/M/B/T suffixes.
 * Sub-cent values show additional precision.
 *   - Values >= 1T are shown as $X.XT
 *   - Values >= 1B are shown as $X.XB
 *   - Values >= 1M are shown as $X.XM
 *   - Values >= 1K are shown as $X.XK
 *   - Otherwise shown as $X.XX
 * @param {number} usd - Cost in USD
 * @returns {string}
 */
export function formatCostAbbreviated(usd: number | null | undefined): string {
  const value = Number(usd || 0);
  if (!Number.isFinite(value) || value === 0) return "$0";
  const abs = Math.abs(value);
  if (abs < 0.01) {
    if (value < 0) {
      return `-$${Math.abs(value).toFixed(6)}`;
    }
    return `$${value.toFixed(6)}`;
  }
  let divisor: number, suffix: string;
  if (abs >= 1_000_000_000_000) {
    divisor = 1_000_000_000_000;
    suffix = "T";
  } else if (abs >= 1_000_000_000) {
    divisor = 1_000_000_000;
    suffix = "B";
  } else if (abs >= 1_000_000) {
    divisor = 1_000_000;
    suffix = "M";
  } else if (abs >= 1_000) {
    divisor = 1_000;
    suffix = "K";
  } else {
    if (value < 0) {
      return `-$${Math.abs(value).toFixed(2)}`;
    }
    return `$${value.toFixed(2)}`;
  }
  const abbreviated = abs / divisor;
  let formatted = abbreviated.toFixed(1);
  if (formatted.includes(".")) {
    formatted = formatted.replace(/\.?0+$/, "");
  }
  const sign = value < 0 ? "-" : "";
  return `${sign}$${formatted}${suffix}`;
}

/**
 * Truncate a URL for compact display.
 * @param {string} url - Full URL
 * @param {number} max - Maximum characters (default: 50)
 * @returns {string}
 */
export function truncateUrl(url: string | null | undefined, max = 50) {
  if (!url) return "-";
  try {
    const parsed = new URL(url);
    const display = parsed.hostname + parsed.pathname;
    return display.length > max ? display.slice(0, max) + "…" : display;
  } catch {
    return url.length > max ? url.slice(0, max) + "…" : url;
  }
}

/**
 * Safely extract a finite number, returning undefined for invalid values.
 * Used by quota normalization in both backend (quotaCache) and frontend (ProviderLimits).
 */
export function safePercentage(value: unknown): number | undefined {
  return typeof value === "number" && isFinite(value) ? value : undefined;
}
