#!/usr/bin/env ruby

require_relative 'shared_constants'

module OutputFormatter
  extend self

  # Format a tabbed entry with consistent spacing
  def format_tabbed_entry(left_text, right_text, indent_level = 1)
    tabs = SharedConstants::Formatting::INDENT_LEVEL_1 * indent_level
    "#{tabs}#{left_text}\t#{right_text}"
  end

  # Format a substance entry with optional average
  def format_substance_with_average(substance, count, average = nil)
    avg_text = average ? " (avg #{average}mg)" : ""
    format_tabbed_entry(substance, "#{count} uses#{avg_text}", 2)
  end

  # Format a substance entry with count only
  def format_substance_entry(substance, count, indent_level = 1)
    format_tabbed_entry(substance, "#{count} uses", indent_level)
  end

  # Format a route entry with usage statistics
  def format_route_entry(substance, route, count, total, indent_level = 1)
    percentage = total > 0 ? (count.to_f / total * 100).round(1) : 0
    format_tabbed_entry(substance, "#{route} (#{count}/#{total} uses, #{percentage}%)", indent_level)
  end

  # Format a time period entry
  def format_time_period_entry(period, count, indent_level = 1)
    format_tabbed_entry(period, "#{count} total uses", indent_level)
  end

  # Format a day of week entry
  def format_day_entry(day, count, indent_level = 1)
    format_tabbed_entry(day, "#{count} uses", indent_level)
  end

  # Format a streak entry
  def format_streak_entry(substance, days, indent_level = 1)
    format_tabbed_entry(substance, "#{days} days", indent_level)
  end

  # Format a dose entry for hardest day
  def format_dose_entry(time, substance, dose, route, indent_level = 1)
    dose_text = dose && !dose.empty? ? " #{dose}" : ""
    format_tabbed_entry(time, "#{substance}#{dose_text} (#{route})", indent_level)
  end

  # Format a month header
  def format_month_header(month_string, year)
    month_name = Date.strptime(month_string, '%Y-%m').strftime('%B')
    "#{SharedConstants::Formatting::INDENT_LEVEL_2}#{month_name} #{year}:"
  end

  # Format a section header with consistent styling
  def format_section_header(title, level = 1)
    case level
    when 1
      "**#{title}**"
    when 2
      "#{SharedConstants::Formatting::INDENT_LEVEL_1}**#{title}**"
    when 3
      "#{SharedConstants::Formatting::INDENT_LEVEL_2}**#{title}**"
    else
      title
    end
  end

  # Format a comment with proper indentation
  def format_comment(comment, indent_level = 1)
    return nil if comment.nil? || comment.empty?
    
    tabs = SharedConstants::Formatting::INDENT_LEVEL_1 * indent_level
    "#{tabs}#{comment}"
  end

  # Format a multi-line block with consistent indentation
  def format_block(lines, indent_level = 1)
    return [] if lines.nil? || lines.empty?
    
    tabs = SharedConstants::Formatting::INDENT_LEVEL_1 * indent_level
    lines.map { |line| "#{tabs}#{line}" }
  end

  # Format a table with aligned columns
  def format_table(headers, rows, indent_level = 1)
    return [] if headers.nil? || rows.nil? || rows.empty?
    
    # Calculate column widths
    all_rows = [headers] + rows
    col_widths = headers.each_with_index.map do |_, i|
      all_rows.map { |row| row[i].to_s.length }.max
    end
    
    # Format header
    header_line = format_table_row(headers, col_widths, indent_level)
    separator = format_table_separator(col_widths, indent_level)
    
    # Format data rows
    data_lines = rows.map { |row| format_table_row(row, col_widths, indent_level) }
    
    [header_line, separator] + data_lines
  end

  # Format a percentage with consistent precision
  def format_percentage(value, precision = 1)
    return "0.0%" if value.nil?
    "#{value.round(precision)}%"
  end

  # Format a count with optional total
  def format_count(count, total = nil)
    return "0" if count.nil?
    
    if total
      "#{count}/#{total}"
    else
      count.to_s
    end
  end

  # Format a dose amount with proper precision
  def format_dose_amount(amount, unit = 'mg')
    return "" if amount.nil?
    
    if amount.is_a?(Float)
      "#{amount.round(1)}#{unit}"
    else
      "#{amount}#{unit}"
    end
  end

  # Format a time period with proper styling
  def format_time_period(period_name, count, total = nil)
    if total && total > 0
      percentage = (count.to_f / total * 100).round(1)
      "#{period_name}: #{count} uses (#{percentage}%)"
    else
      "#{period_name}: #{count} uses"
    end
  end

  # Format a date range
  def format_date_range(start_date, end_date)
    return "" if start_date.nil?
    
    if end_date.nil?
      start_date.strftime('%B %d, %Y')
    else
      "#{start_date.strftime('%B %d')} - #{end_date.strftime('%B %d, %Y')}"
    end
  end

  # Format a list with consistent bullet points
  def format_list(items, bullet = '•', indent_level = 1)
    return [] if items.nil? || items.empty?
    
    tabs = SharedConstants::Formatting::INDENT_LEVEL_1 * indent_level
    items.map { |item| "#{tabs}#{bullet} #{item}" }
  end

  # Format a key-value pair
  def format_key_value(key, value, separator = ':', indent_level = 1)
    tabs = SharedConstants::Formatting::INDENT_LEVEL_1 * indent_level
    "#{tabs}#{key}#{separator} #{value}"
  end

  # Format a summary statistic
  def format_summary_stat(label, value, indent_level = 1)
    format_tabbed_entry(label, value.to_s, indent_level)
  end

  # Truncate text with ellipsis if too long
  def truncate_text(text, max_length = SharedConstants::Bot::MAX_RESPONSE_LENGTH)
    return text if text.nil? || text.length <= max_length
    
    truncated = text[0, max_length - SharedConstants::Bot::TRUNCATION_SUFFIX.length]
    "#{truncated}#{SharedConstants::Bot::TRUNCATION_SUFFIX}"
  end

  # Add section with optional comment
  def add_section(output, title, comment = nil)
    output << ""
    output << format_section_header(title)
    
    if comment
      output << format_comment(comment)
      output << ""
    end
    
    yield(output) if block_given?
  end

  private

  # Format a single table row
  def format_table_row(row, col_widths, indent_level)
    tabs = SharedConstants::Formatting::INDENT_LEVEL_1 * indent_level
    formatted_cells = row.each_with_index.map do |cell, i|
      cell.to_s.ljust(col_widths[i])
    end
    "#{tabs}#{formatted_cells.join(' | ')}"
  end

  # Format table separator
  def format_table_separator(col_widths, indent_level)
    tabs = SharedConstants::Formatting::INDENT_LEVEL_1 * indent_level
    separators = col_widths.map { |width| '-' * width }
    "#{tabs}#{separators.join('-+-')}"
  end
end