/**
 * String Utilities - Core Module
 *
 * Framework-agnostic string manipulation and formatting functions.
 * Can be used in any project (NestJS, Express, Frontend, etc.)
 *
 * @module @core/utils/string
 * @version 1.0.0
 */

/**
 * Generate slug from string
 * @example slugify("Hello World!") => "hello-world"
 */
export const slugify = (text: string): string => {
  return text
    .toString()
    .toLowerCase()
    .trim()
    .replace(/\s+/g, '-')
    .replace(/[^\w-]+/g, '')
    .replace(/--+/g, '-')
    .replace(/^-+/, '')
    .replace(/-+$/, '');
};

/**
 * Capitalize first letter
 * @example capitalize("hello") => "Hello"
 */
export const capitalize = (text: string): string => {
  if (!text) return '';
  return text.charAt(0).toUpperCase() + text.slice(1).toLowerCase();
};

/**
 * Capitalize each word
 * @example capitalizeWords("hello world") => "Hello World"
 */
export const capitalizeWords = (text: string): string => {
  return text
    .split(' ')
    .map((word) => capitalize(word))
    .join(' ');
};

/**
 * Truncate string with ellipsis
 * @example truncate("Hello World", 8) => "Hello..."
 */
export const truncate = (text: string, maxLength: number): string => {
  if (text.length <= maxLength) return text;
  return text.substring(0, maxLength - 3) + '...';
};

/**
 * Remove HTML tags
 * @example stripHtml("<p>Hello</p>") => "Hello"
 */
export const stripHtml = (html: string): string => {
  return html.replace(/<[^>]*>/g, '');
};

/**
 * Sanitize string (remove special chars except spaces)
 */
export const sanitize = (text: string): string => {
  return text.replace(/[^\w\s]/gi, '');
};

/**
 * Check if string is empty or whitespace
 */
export const isEmpty = (text: string | null | undefined): boolean => {
  return !text || text.trim().length === 0;
};

/**
 * Check if string is not empty
 */
export const isNotEmpty = (text: string | null | undefined): boolean => {
  return !isEmpty(text);
};

/**
 * Generate random string
 * @param length - Length of string (default: 10)
 * @param charset - Character set to use (default: alphanumeric)
 */
export const randomString = (
  length: number = 10,
  charset: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
): string => {
  let result = '';
  for (let i = 0; i < length; i++) {
    result += charset.charAt(Math.floor(Math.random() * charset.length));
  }
  return result;
};

/**
 * Generate random numeric string
 */
export const randomNumeric = (length: number = 6): string => {
  return randomString(length, '0123456789');
};

/**
 * Mask sensitive data (show only last N chars)
 * @example maskString("1234567890", 4) => "******7890"
 */
export const maskString = (text: string, visibleChars: number = 4): string => {
  if (text.length <= visibleChars) return text;
  const masked = '*'.repeat(text.length - visibleChars);
  return masked + text.slice(-visibleChars);
};

/**
 * Mask email (show first 2 chars and domain)
 * @example maskEmail("john@example.com") => "jo***@example.com"
 */
export const maskEmail = (email: string): string => {
  const [local, domain] = email.split('@');
  if (!domain) return email;
  const maskedLocal = local.substring(0, 2) + '***';
  return `${maskedLocal}@${domain}`;
};

/**
 * Convert string to camelCase
 * @example toCamelCase("hello world") => "helloWorld"
 */
export const toCamelCase = (text: string): string => {
  return text
    .replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) =>
      index === 0 ? word.toLowerCase() : word.toUpperCase(),
    )
    .replace(/\s+/g, '');
};

/**
 * Convert string to snake_case
 * @example toSnakeCase("helloWorld") => "hello_world"
 */
export const toSnakeCase = (text: string): string => {
  return text
    .replace(/([A-Z])/g, '_$1')
    .toLowerCase()
    .replace(/^_/, '')
    .replace(/\s+/g, '_');
};

/**
 * Convert string to kebab-case
 * @example toKebabCase("helloWorld") => "hello-world"
 */
export const toKebabCase = (text: string): string => {
  return text
    .replace(/([A-Z])/g, '-$1')
    .toLowerCase()
    .replace(/^-/, '')
    .replace(/\s+/g, '-');
};

/**
 * Convert string to CONSTANT_CASE
 * @example toConstantCase("helloWorld") => "HELLO_WORLD"
 */
export const toConstantCase = (text: string): string => {
  return toSnakeCase(text).toUpperCase();
};

/**
 * Convert string to PascalCase
 * @example toPascalCase("hello world") => "HelloWorld"
 */
export const toPascalCase = (text: string): string => {
  return text
    .replace(/(?:^\w|[A-Z]|\b\w)/g, (word) => word.toUpperCase())
    .replace(/\s+/g, '');
};

/**
 * Escape regex special characters
 */
export const escapeRegex = (text: string): string => {
  return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
};

/**
 * Count words in string
 */
export const wordCount = (text: string): number => {
  if (isEmpty(text)) return 0;
  return text.trim().split(/\s+/).length;
};

/**
 * Reverse string
 */
export const reverse = (text: string): string => {
  return text.split('').reverse().join('');
};

/**
 * Pad string on left
 * @example padLeft("5", 3, "0") => "005"
 */
export const padLeft = (text: string, length: number, char: string = ' '): string => {
  return text.padStart(length, char);
};

/**
 * Pad string on right
 * @example padRight("5", 3, "0") => "500"
 */
export const padRight = (text: string, length: number, char: string = ' '): string => {
  return text.padEnd(length, char);
};

/**
 * Remove accents from string
 * @example removeAccents("café") => "cafe"
 */
export const removeAccents = (text: string): string => {
  return text.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
};

/**
 * Extract initials from name
 * @example getInitials("John Doe") => "JD"
 */
export const getInitials = (name: string, maxChars: number = 2): string => {
  return name
    .split(' ')
    .map((word) => word.charAt(0).toUpperCase())
    .slice(0, maxChars)
    .join('');
};

/**
 * Format number as currency string
 * @example formatCurrency(1234.5, "USD") => "$1,234.50"
 */
export const formatCurrency = (
  amount: number,
  currency: string = 'USD',
  locale: string = 'en-US',
): string => {
  return new Intl.NumberFormat(locale, {
    style: 'currency',
    currency,
  }).format(amount);
};

/**
 * Format number with thousands separator
 * @example formatNumber(1234567) => "1,234,567"
 */
export const formatNumber = (num: number, locale: string = 'en-US'): string => {
  return new Intl.NumberFormat(locale).format(num);
};

/**
 * Parse query string to object
 * @example parseQueryString("?foo=bar&baz=qux") => { foo: "bar", baz: "qux" }
 */
export const parseQueryString = (queryString: string): Record<string, string> => {
  const params = new URLSearchParams(queryString);
  const result: Record<string, string> = {};
  params.forEach((value, key) => {
    result[key] = value;
  });
  return result;
};

/**
 * Build query string from object
 * @example buildQueryString({ foo: "bar", baz: "qux" }) => "foo=bar&baz=qux"
 */
export const buildQueryString = (params: Record<string, string | number | boolean>): string => {
  return Object.entries(params)
    .filter(([, value]) => value !== undefined && value !== null)
    .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
    .join('&');
};
