/**
 * Format a date string to a more readable format
 */
export function formatDate(dateString: string): string {
  const date = new Date(dateString);
  return date.toLocaleDateString('zh-CN', {
    year: 'numeric',
    month: 'long',
    day: 'numeric'
  });
}

/**
 * Truncate text to a specified length with ellipsis
 */
export function truncateText(text: string, maxLength: number): string {
  if (text.length <= maxLength) return text;
  return text.slice(0, maxLength) + '...';
}

/**
 * Normalize FontAwesome icon class
 */
export function normalizeFaIcon(icon: unknown): string {
  const raw = typeof icon === 'string' ? icon.trim() : '';
  if (!raw) return 'fa-folder';

  if (raw.includes('fa-')) {
    const parts = raw.split(/\s+/);
    for (let i = parts.length - 1; i >= 0; i -= 1) {
      const t = parts[i];
      if (t?.startsWith('fa-')) return t;
    }
    return 'fa-folder';
  }

  return 'fa-folder';
}

/**
 * Resolve file reference (for images)
 */
export function resolveFileRef(ref: string): string {
  if (ref.startsWith('http://') || ref.startsWith('https://') || ref.startsWith('/')) {
    return ref;
  }
  return `/uploads/${ref}`;
}

function resolveTaxonomyToken(
  value:
    | string
    | null
    | undefined
    | {
        slug?: string | null;
        name?: string | null;
      },
): string {
  if (typeof value === 'string') {
    return value.trim();
  }

  return (value?.slug || value?.name || '').trim();
}

export function buildCategoryUrl(
  value:
    | string
    | null
    | undefined
    | {
        slug?: string | null;
        name?: string | null;
      },
): string {
  const token = resolveTaxonomyToken(value);
  return token ? `/categories/${encodeURIComponent(token)}` : '/categories';
}

export function buildTagUrl(
  value:
    | string
    | null
    | undefined
    | {
        slug?: string | null;
        name?: string | null;
      },
): string {
  const token = resolveTaxonomyToken(value);
  return token ? `/tags/${encodeURIComponent(token)}` : '/tags';
}

/**
 * Generate a unique ID
 */
export function generateId(): string {
  return Math.random().toString(36).substring(2, 9);
}

/**
 * Debounce function
 */
export function debounce<T extends (...args: unknown[]) => unknown>(
  func: T,
  wait: number
): (...args: Parameters<T>) => void {
  let timeout: ReturnType<typeof setTimeout> | null = null;
  return (...args: Parameters<T>) => {
    if (timeout) clearTimeout(timeout);
    timeout = setTimeout(() => func(...args), wait);
  };
}

export interface AccentTheme {
  color: string;
  rgb: string;
}

const POST_TYPE_THEMES: Record<string, AccentTheme> = {
  article: {
    color: '#2563eb',
    rgb: '37 99 235',
  },
  tweet: {
    color: '#f97316',
    rgb: '249 115 22',
  },
};

const DEFAULT_THEME: AccentTheme = {
  color: '#64748b',
  rgb: '100 116 139',
};

function normalizeToken(value: string | null | undefined): string {
  return value?.trim().toLowerCase() || '';
}

function hashToken(value: string): number {
  let hash = 2166136261;

  for (let index = 0; index < value.length; index += 1) {
    hash ^= value.charCodeAt(index);
    hash = Math.imul(hash, 16777619);
  }

  return hash >>> 0;
}

function hexToRgbTriplet(hex: string): string {
  const normalized = hex.replace('#', '');
  const safeHex = normalized.length === 3
    ? normalized.split('').map((char) => `${char}${char}`).join('')
    : normalized;
  const value = parseInt(safeHex, 16);

  return `${(value >> 16) & 255} ${(value >> 8) & 255} ${value & 255}`;
}

function hslToHex(hue: number, saturation: number, lightness: number): string {
  const normalizedHue = ((hue % 360) + 360) % 360;
  const s = saturation / 100;
  const l = lightness / 100;
  const chroma = (1 - Math.abs(2 * l - 1)) * s;
  const section = normalizedHue / 60;
  const x = chroma * (1 - Math.abs((section % 2) - 1));

  let red = 0;
  let green = 0;
  let blue = 0;

  if (section >= 0 && section < 1) {
    red = chroma;
    green = x;
  } else if (section < 2) {
    red = x;
    green = chroma;
  } else if (section < 3) {
    green = chroma;
    blue = x;
  } else if (section < 4) {
    green = x;
    blue = chroma;
  } else if (section < 5) {
    red = x;
    blue = chroma;
  } else {
    red = chroma;
    blue = x;
  }

  const match = l - chroma / 2;
  const toHex = (value: number) => Math.round((value + match) * 255).toString(16).padStart(2, '0');

  return `#${toHex(red)}${toHex(green)}${toHex(blue)}`;
}

function getGeneratedTheme(
  value: string | null | undefined,
  {
    salt,
    saturation,
    lightness,
  }: {
    salt: string;
    saturation: number;
    lightness: number;
  }
): AccentTheme {
  const normalized = normalizeToken(value);

  if (!normalized) {
    return DEFAULT_THEME;
  }

  const hue = hashToken(`${salt}:${normalized}`) % 360;
  const color = hslToHex(hue, saturation, lightness);

  return {
    color,
    rgb: hexToRgbTriplet(color),
  };
}

export function getAccentVars(theme: AccentTheme): string {
  return [
    `--accent-color:${theme.color}`,
    `--accent-rgb:${theme.rgb}`,
    `--pill-fg:${theme.color}`,
    `--pill-rgb:${theme.rgb}`,
    `--tile-rgb:${theme.rgb}`,
  ].join(';') + ';';
}

export function getPostTypeTheme(type: string | null | undefined): AccentTheme {
  return POST_TYPE_THEMES[normalizeToken(type)] || DEFAULT_THEME;
}

export function getCategoryTheme(category: string | null | undefined): AccentTheme {
  return getGeneratedTheme(category, {
    salt: 'category',
    saturation: 72,
    lightness: 46,
  });
}

export function getTagTheme(tag: string | null | undefined): AccentTheme {
  return getGeneratedTheme(tag, {
    salt: 'tag',
    saturation: 68,
    lightness: 50,
  });
}

/**
 * Filter posts by type and tag
 */
export function filterPosts(
  posts: Array<{
    type: string;
    tags: string[];
  }>,
  postType: string,
  tag: string
): typeof posts {
  return posts.filter(post => {
    if (postType !== 'all' && post.type !== postType) return false;
    if (tag && !post.tags.includes(tag)) return false;
    return true;
  });
}

/**
 * Get color for post type
 */
export function getPostTypeColor(type: string): string {
  return getPostTypeTheme(type).color;
}

export {
  buildParagraphDescriptors,
  createParagraphExcerpt,
  fnv1aHash,
  normalizeParagraphText,
} from './paragraph-comments';
