class StatsController < ApplicationController

  before_action :users_only
  before_action :load_user
  before_action :check_ownership

  # only the current user
  def load_user
    @user = current_user
    @check_ownership_of = @user
  end

  # gather statistics for the user on all their works
  def index
    user_works = Work.joins(pseuds: :user).where(users: { id: @user.id }).where(posted: true)
    user_chapters = Chapter.joins(pseuds: :user).where(users: { id: @user.id }).where(posted: true)
    work_query = user_works
      .joins(:taggings)
      .joins("inner join tags on taggings.tagger_id = tags.id AND tags.type = 'Fandom'")
      .select("distinct tags.name as fandom, works.id as id, works.title as title")

    # sort

    # NOTE: Because we are going to be eval'ing the @sort variable later we MUST make sure that its content is
    # checked against the allowlist of valid options
    sort_options = %w[hits date kudos.count comment_thread_count bookmarks.count subscriptions.count word_count]
    @sort = sort_options.include?(params[:sort_column]) ? params[:sort_column] : "hits"

    @dir = params[:sort_direction] == "ASC" ? "ASC" : "DESC"
    params[:sort_column] = @sort
    params[:sort_direction] = @dir

    # gather works and sort by specified count
    @years = ["All Years"] + user_chapters.pluck(:published_at).map { |date| date.year.to_s }
      .uniq.sort
    @current_year = @years.include?(params[:year]) ? params[:year] : "All Years"
    if @current_year == "All Years"
      work_query = work_query.select("works.revised_at as date, works.word_count as word_count")
    else
      next_year = @current_year.to_i + 1
      start_date = DateTime.parse("01/01/#{@current_year}")
      end_date = DateTime.parse("01/01/#{next_year}")
      work_query = work_query
        .joins(:chapters)
        .where("chapters.posted = 1 AND chapters.published_at >= ? AND chapters.published_at < ?", start_date, end_date)
        .select("CONVERT(MAX(chapters.published_at), datetime) as date, SUM(chapters.word_count) as word_count")
        .group(:id, :fandom)
    end
    works = work_query.all.sort_by { |w| @dir == "ASC" ? (stat_element(w, @sort) || 0) : (0 - (stat_element(w, @sort) || 0).to_i) }

    # on the off-chance a new user decides to look at their stats and have no works
    render "no_stats" and return if works.blank?

    # group by fandom or flat view
    if params[:flat_view]
      @works = {ts("All Fandoms") => works.uniq}
    else
      @works = works.group_by(&:fandom)
    end

    # gather totals for all works
    @totals = {}
    (sort_options - ["date"]).each do |value|
      # the inject is used to collect the sum in the "result" variable as we iterate over all the works
      @totals[value.split(".")[0].to_sym] = works.uniq.inject(0) { |result, work| result + (stat_element(work, value) || 0) } # sum the works
    end
    @totals[:user_subscriptions] = Subscription.where(subscribable_id: @user.id, subscribable_type: 'User').count

    # graph top 5 works
    @chart_data = GoogleVisualr::DataTable.new
    @chart_data.new_column('string', 'Title')

    chart_col = @sort == "date" ? "hits" : @sort
    chart_col_title = chart_col.split(".")[0].titleize == "Comments" ? ts("Comment Threads") : chart_col.split(".")[0].titleize
    if @sort == "date" && @dir == "ASC"
      chart_title = ts("Oldest")
    elsif @sort == "date" && @dir == "DESC"
      chart_title = ts("Most Recent")
    elsif @dir == "ASC"
      chart_title = ts("Bottom Five By #{chart_col_title}")
    else
      chart_title = ts("Top Five By #{chart_col_title}")
    end
    @chart_data.new_column('number', chart_col_title)

    # Add Rows and Values
    @chart_data.add_rows(works.uniq[0..4].map { |w| [w.title, stat_element(w, chart_col)] })

    # image version of bar chart
    # opts from here: http://code.google.com/apis/chart/image/docs/gallery/bar_charts.html
    @image_chart = GoogleVisualr::Image::BarChart.new(@chart_data, {isVertical: true}).uri({
     chtt: chart_title,
     chs: "800x350",
     chbh: "a",
     chxt: "x",
     chm: "N,000000,0,-1,11"
    })

    options = {
      colors: ["#993333"],
      title: chart_title,
      vAxis: {
        viewWindow: { min: 0 }
      }
    }
    @chart = GoogleVisualr::Interactive::ColumnChart.new(@chart_data, options)

  end

  private

  def stat_element(work, element)
    case element.downcase
    when "date"
      work.date
    when "hits"
      work.hits
    when "kudos.count"
      work.kudos.count
    when "comment_thread_count"
      work.comment_thread_count
    when "bookmarks.count"
      work.bookmarks.count
    when "subscriptions.count"
      work.subscriptions.count
    when "word_count"
      work.word_count
    end
  end
end
