class Board < ApplicationRecord
  belongs_to :game
  belongs_to :creator, class_name: "Participant",
             foreign_key: "created_by_participant_id", optional: true
  has_many :board_memberships, dependent: :destroy
  has_many :active_memberships, -> { where(left_at: nil) },
           class_name: "BoardMembership"
  has_many :participants, through: :board_memberships
  has_many :board_posts, dependent: :destroy
  has_many :board_proposals, dependent: :destroy

  enum :board_type, { global: "global", negotiation: "negotiation" }

  validate :no_duplicate_member_combination, if: :negotiation?

  # メンバーかどうか判定（退出済みはfalse）
  def member?(participant)
    return false unless participant
    board_memberships.exists?(participant_id: participant.id, left_at: nil)
  end

  # 履歴モードかどうか（ゲーム終了後は常にtrue）
  def history_mode?
    game.status == "finished"
  end

  # 指定した参加者の未読件数を取得
  def unread_count_for(participant)
    return 0 unless participant

    membership = board_memberships.find_by(participant_id: participant.id)
    # メンバーでない、または退出済みの場合は未読なしとする（あるいは全件とするか要検討だが、一旦0）
    return 0 unless membership && membership.active?

    last_id = membership.last_read_post_id || 0
    board_posts.where("id > ?", last_id).count
  end

  private

  def no_duplicate_member_combination
    # 新規作成時のみチェック（更新時はメンバー変動があるため別途考慮が必要だが、今回は作成時のみ想定）
    # ただしメンバー追加時にもチェックが必要になる可能性があるため、Boardモデルのバリデーションとして定義

    # 比較対象のメンバーIDリスト（ソート済み）
    current_member_ids = board_memberships.map(&:participant_id).sort

    # 同じゲーム内の他の交渉用掲示板を検索
    game.boards.negotiation.where.not(id: id).each do |other_board|
      # 退出者を含めた全メンバー構成で比較するか、アクティブメンバーのみで比較するか
      # 仕様書「同じメンバー構成の掲示板は作成できない」
      # ここでは「現在参加しているメンバー」の構成が重複しないようにする
      other_member_ids = other_board.board_memberships.where(left_at: nil).pluck(:participant_id).sort

      if other_member_ids == current_member_ids
        errors.add(:base, "同じメンバー構成の掲示板がすでに存在します")
        return
      end
    end
  end
end
