# frozen_string_literal: true

class TopicFeaturedUsers
  attr_reader :topic

  def initialize(topic)
    @topic = topic
  end

  def self.count
    4
  end

  # Chooses which topic users to feature
  def choose(args = {})
    self.class.ensure_consistency!(topic.id.to_i)
    update_participant_count
  end

  def user_ids
    [
      topic.featured_user1_id,
      topic.featured_user2_id,
      topic.featured_user3_id,
      topic.featured_user4_id,
    ].uniq.compact
  end

  def self.ensure_consistency!(topic_id = nil)
    filter = "#{"AND t.id = #{topic_id.to_i}" if topic_id}"
    filter2 = "#{"AND tt.id = #{topic_id.to_i}" if topic_id}"

    sql = <<SQL

WITH cte as (
    SELECT
        t.id,
        p.user_id,
        MAX(p.created_at) last_post_date,
        ROW_NUMBER() OVER(PARTITION BY t.id ORDER BY COUNT(*) DESC, MAX(p.created_at) DESC) as rank
    FROM topics t
    JOIN posts p ON p.topic_id = t.id
    WHERE p.deleted_at IS NULL AND
          NOT p.hidden AND
          p.post_type in (#{Topic.visible_post_types.join(",")}) AND
          p.user_id <> t.user_id AND
          p.user_id <> t.last_post_user_id
          #{filter}
    GROUP BY t.id, p.user_id
),

cte2 as (
  SELECT id, user_id, ROW_NUMBER() OVER(PARTITION BY id ORDER BY last_post_date ASC) as rank
  FROM cte
  WHERE rank <= #{count}
)

UPDATE topics tt
SET
  featured_user1_id = x.featured_user1,
  featured_user2_id = x.featured_user2,
  featured_user3_id = x.featured_user3,
  featured_user4_id = x.featured_user4
FROM topics AS tt2
LEFT OUTER JOIN (
  SELECT
      c.id,
      MAX(case when c.rank = 1 then c.user_id end) featured_user1,
      MAX(case when c.rank = 2 then c.user_id end) featured_user2,
      MAX(case when c.rank = 3 then c.user_id end) featured_user3,
      MAX(case when c.rank = 4 then c.user_id end) featured_user4
  FROM cte2 as c
  GROUP BY c.id
) x ON x.id = tt2.id
WHERE tt.id = tt2.id AND
(
  COALESCE(tt.featured_user1_id,-99) <> COALESCE(x.featured_user1,-99) OR
  COALESCE(tt.featured_user2_id,-99) <> COALESCE(x.featured_user2,-99) OR
  COALESCE(tt.featured_user3_id,-99) <> COALESCE(x.featured_user3,-99) OR
  COALESCE(tt.featured_user4_id,-99) <> COALESCE(x.featured_user4,-99)
)
#{filter2}
SQL

    DB.exec(sql)
  end

  private

  def update_participant_count
    count =
      topic
        .posts
        .where("NOT hidden AND post_type in (?)", Topic.visible_post_types)
        .count("distinct user_id")
    topic.update_columns(participant_count: count)
  end
end