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

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

export function formatBytes(bytes: number, decimals = 2) {
  if (bytes === 0) return '0 Bytes'

  const k = 1024
  const dm = decimals < 0 ? 0 : decimals
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']

  const i = Math.floor(Math.log(bytes) / Math.log(k))

  return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]
}

export function formatDate(date: string | undefined | null) {
  if (!date) return 'N/A'
  // Ensure date is a string (guard against Date objects or numbers)
  if (typeof date !== 'string') {
    date = String(date)
  }

  // Database stores dates as 'YYYY-MM-DD HH:MM:SS' in UTC (SQLite CURRENT_TIMESTAMP)
  // Parse as UTC and convert to local time for display
  const d = date.includes(' ')
    ? new Date(date.replace(' ', 'T') + 'Z')  // UTC from database
    : new Date(date)  // Already has timezone or is ISO format

  return d.toLocaleString('en-US', {
    year: 'numeric',
    month: 'short',
    day: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
    hour12: true
  })
}

export function formatDateOnly(date: string | undefined | null) {
  if (!date) return 'N/A'
  // Ensure date is a string (guard against Date objects or numbers)
  if (typeof date !== 'string') {
    date = String(date)
  }

  // Parse date - handles ISO format (2024-03-15T00:00:00) and simple date (2024-03-15)
  const d = date.includes(' ')
    ? new Date(date.replace(' ', 'T') + 'Z')
    : new Date(date)

  return d.toLocaleDateString('en-US', {
    year: 'numeric',
    month: 'short',
    day: 'numeric'
  })
}

export function formatRelativeTime(date: string) {
  if (!date) return 'N/A'
  // Ensure date is a string (guard against Date objects or numbers)
  if (typeof date !== 'string') {
    date = String(date)
  }

  const now = new Date()

  // Handle different date formats:
  // - Scheduler API returns local ISO format: "2025-10-30T10:41:30.722479"
  // - Database returns UTC format: "2025-10-30 10:41:30" (SQLite CURRENT_TIMESTAMP)
  let then: Date

  if (date.includes('T') && !date.endsWith('Z') && date.match(/T\d{2}:\d{2}:\d{2}\.\d+$/)) {
    // Local timestamp from scheduler API (has 'T' and microseconds, no 'Z')
    // Parse as local time directly - do NOT append 'Z'
    then = new Date(date)
  } else if (date.includes(' ')) {
    // UTC timestamp from database (SQLite CURRENT_TIMESTAMP is UTC)
    // Append 'Z' to indicate UTC timezone
    then = new Date(date.replace(' ', 'T') + 'Z')
  } else {
    // Already has timezone or is ISO format
    then = new Date(date)
  }

  const diff = now.getTime() - then.getTime()

  const seconds = Math.floor(diff / 1000)
  const minutes = Math.floor(seconds / 60)
  const hours = Math.floor(minutes / 60)
  const days = Math.floor(hours / 24)

  // Handle future times (next scheduled runs)
  if (seconds < 0) {
    const absSeconds = Math.abs(seconds)
    const absMinutes = Math.floor(absSeconds / 60)
    const absHours = Math.floor(absMinutes / 60)
    const absDays = Math.floor(absHours / 24)

    if (absSeconds < 60) return 'now'
    if (absMinutes < 60) return `in ${absMinutes}m`
    if (absHours < 24) return `in ${absHours}h ${absMinutes % 60}m`
    return `in ${absDays}d ${absHours % 24}h`
  }

  if (seconds < 60) return 'just now'
  if (minutes < 60) return `${minutes}m ago`
  if (hours < 24) return `${hours}h ago`
  if (days < 7) return `${days}d ago`

  return formatDate(date)
}

/**
 * Check if a filename or path represents a video file.
 * Centralized utility to avoid duplication across components.
 */
export function isVideoFile(filename: string | undefined | null): boolean {
  if (!filename) return false
  return /\.(mp4|mov|webm|avi|mkv|flv|m4v|wmv|mpg|mpeg)$/i.test(filename)
}

/**
 * Get the media type string based on filename.
 */
export function getMediaType(filename: string | undefined | null): 'video' | 'image' {
  return isVideoFile(filename) ? 'video' : 'image'
}

export function formatPlatformName(platform: string | null | undefined): string {
  if (!platform) return 'Unknown'

  const platformNames: Record<string, string> = {
    // Social media platforms
    'instagram': 'Instagram',
    'fastdl': 'Instagram',
    'imginn': 'Instagram',
    'instagram_client': 'Instagram',
    'toolzu': 'Instagram',
    'snapchat': 'Snapchat',
    'tiktok': 'TikTok',
    'twitter': 'Twitter',
    'x': 'Twitter',
    'reddit': 'Reddit',
    // YouTube
    'youtube': 'YouTube',
    'youtube_monitor': 'YouTube',
    'youtube_channel_monitor': 'YouTube',
    // Twitch
    'twitch': 'Twitch',
    // Pornhub
    'pornhub': 'Pornhub',
    'xhamster': 'xHamster',
    // Paid content platforms
    'paid_content': 'Paid Content',
    'fansly': 'Fansly',
    'fansly_direct': 'Fansly',
    'onlyfans': 'OnlyFans',
    'onlyfans_direct': 'OnlyFans',
    'coomer': 'Coomer',
    'kemono': 'Kemono',
    // Usenet
    'easynews': 'Easynews',
    'easynews_monitor': 'Easynews',
    'nzb': 'NZB',
    // Forums & galleries
    'forum': 'Forums',
    'forums': 'Forums',
    'forum_monitor': 'Forums',
    'monitor': 'Forum Monitor',
    'coppermine': 'Coppermine',
    'bellazon': 'Bellazon',
    'hqcelebcorner': 'HQCelebCorner',
    'picturepub': 'PicturePub',
    'soundgasm': 'Soundgasm',
    // Appearances & media databases
    'appearances': 'Appearances',
    'appearances_sync': 'Appearances',
    'tmdb': 'TMDb',
    'tvdb': 'TVDB',
    'imdb': 'IMDb',
    'plex': 'Plex',
    'press': 'Press',
    // Video platforms
    'vimeo': 'Vimeo',
    'dailymotion': 'Dailymotion',
    // Other
    'other': 'Other',
    'unknown': 'Unknown'
  }

  const key = platform.toLowerCase()
  if (platformNames[key]) {
    return platformNames[key]
  }

  // Handle underscore-separated names like "easynews_monitor" -> "Easynews Monitor"
  // But first check if we have a specific mapping
  const withoutSuffix = key.replace(/_monitor$|_sync$|_channel$/, '')
  if (platformNames[withoutSuffix]) {
    return platformNames[withoutSuffix]
  }

  // Fall back to title case with underscores replaced by spaces
  return platform
    .split('_')
    .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
    .join(' ')
}

/**
 * Get the appropriate thumbnail URL for a media file.
 * Centralizes the logic for determining image vs video type.
 *
 * @param api - The API client instance
 * @param filePath - Path to the media file
 * @param filename - Filename to check for video extensions
 * @param contentType - Optional content type from server (takes precedence)
 */
export function getMediaThumbnailType(filename: string | undefined | null, contentType?: string): 'image' | 'video' {
  if (contentType === 'video') return 'video'
  return isVideoFile(filename) ? 'video' : 'image'
}

/**
 * Format error messages from API responses consistently.
 */
export function decodeHtmlEntities(text: string | null | undefined): string {
  if (!text) return ''
  const textarea = document.createElement('textarea')
  textarea.innerHTML = text
  return textarea.value
}

/**
 * Strip Instagram-style dot spacers from captions.
 * Collapses sequences of lines that are only dots or blank into a
 * single newline, as long as there are at least 3 dot-only lines.
 */
export function cleanCaption(text: string): string {
  // Split into lines, find runs of dot/blank lines, collapse if >=3 dots
  const lines = text.split('\n')
  const result: string[] = []
  let i = 0
  while (i < lines.length) {
    const trimmed = lines[i].trim()
    if (trimmed === '.' || trimmed === '') {
      // Start of a potential spacer block
      let j = i
      let dotCount = 0
      while (j < lines.length) {
        const t = lines[j].trim()
        if (t === '.') { dotCount++; j++ }
        else if (t === '') { j++ }
        else { break }
      }
      if (dotCount >= 3) {
        // Collapse the whole block
        result.push('')
        i = j
      } else {
        // Not enough dots, keep original lines
        result.push(lines[i])
        i++
      }
    } else {
      result.push(lines[i])
      i++
    }
  }
  return result.join('\n')
}

/**
 * Cache buster for thumbnail URLs. Rotates daily so browsers
 * refetch thumbnails once per day but still cache within a day.
 */
export const THUMB_CACHE_V = `v=yt4-${Math.floor(Date.now() / 86_400_000)}`

export function getErrorMessage(error: unknown): string {
  if (error instanceof Error) {
    // Check for API error structure
    const apiError = error as Error & { response?: { data?: { detail?: string } } }
    if (apiError.response?.data?.detail) {
      return apiError.response.data.detail
    }
    return error.message
  }
  if (typeof error === 'string') return error
  return 'An unexpected error occurred'
}
