class ServiceRequest < ApplicationRecord
  include JanusApi

  enum status: {
    waiting: "waiting",
    waiting_for_answer: "waiting_for_answer",
    cancelled: "cancelled",
    in_progress: "in_progress",
    finished: "finished",
    deferred: "deferred"
  }

  belongs_to :client, class_name: "User"
  belongs_to :agent, class_name: "User", optional: true

  has_many :messages, dependent: :destroy
  has_many :logs, dependent: :destroy, class_name: :ServiceRequestLog

  validates :description, :title, :category_id, presence: true

  after_commit :create_janus_videoroom!

  scope :active, lambda {
    where(status: %i[waiting waiting_for_answer in_progress deferred])
  }

  scope :inactive, lambda {
    where(status: %i[cancelled finished])
  }

  scope :today, lambda {
    where(created_at: Time.current.all_day)
  }

  scope :search, lambda { |term|
    joins("
      LEFT OUTER JOIN users clients ON service_requests.client_id = clients.id
      LEFT OUTER JOIN users agents ON service_requests.agent_id = agents.id
    ")
      .where(
        "CONCAT(clients.first_name, ' ', clients.last_name, ' ', clients.email,
        ' ', clients.phone_number, ' ', clients.social_security_number, ' ',
        clients.address, ' ', agents.first_name, ' ', agents.last_name, ' ',
        agents.email, ' ', title, ' ', description, ' ', internal_comment)
        ILIKE :term", term: "%#{term}%"
      )
  }

  def estimated_waiting_time
    requests_count = ServiceRequest.waiting.where("created_at < ?", created_at).count
    seconds = (requests_count * 3.minutes).to_i / [User.online_agents_count, 1].max

    ActiveSupport::Duration.build(seconds).inspect
  end

  def destroy_janus_videoroom!
    return unless JanusApi.destroy_videoroom(id)

    update(janus_videoroom_pin: nil)
  end

  def broadcast_update
    broadcast_update_to %i[agent all_service_requests],
                        target: ActionController::Base.helpers.dom_id(self),
                        partial: "agent/service_requests/service_request",
                        locals: {
                          service_request: self
                        }

    broadcast_update_to %i[agent todays_service_requests],
                        target: ActionController::Base.helpers.dom_id(self),
                        partial: "agent/service_requests/service_request",
                        locals: {
                          service_request: self
                        }
  end

  def broadcast_update_to_reserved_requests
    client.client_service_requests
          .where(status: %i[in_progress waiting waiting_for_answer])
          .or(client.client_service_requests.where(id:))
          .each(&:broadcast_update)
  end

  def prepend_to_todays_requests_list
    broadcast_prepend_to %i[agent todays_service_requests],
                         target: "agent_todays_service_requests",
                         partial: "agent/service_requests/service_request",
                         locals: {
                           service_request: self
                         }
  end

  def prepend_to_all_service_requests_list
    broadcast_prepend_to %i[agent all_service_requests],
                         target: "agent_all_service_requests",
                         partial: "agent/service_requests/service_request",
                         locals: {
                           service_request: self
                         }
  end

  def reserved?
    client && client.client_service_requests.where(status: %i[in_progress waiting_for_answer]).any?
  end

  def reserved_agent
    User.agent.find(client.client_service_requests.where(status: %i[in_progress
                                                                    waiting_for_answer]).pluck(:agent_id).compact.first)
  end

  def show_as_reserved?
    (waiting? || waiting_for_answer? || in_progress?) && reserved?
  end

  def start_video_chat?(current_user)
    return true if waiting? && !reserved?

    return true if %i[waiting waiting_for_answer in_progress].include?(status.to_sym) &&
                   agent == current_user
  end

  def self.categories
    %i[
      car
      education
      finance
      health
      leisure
      living
      official_channel
      shop
      work
      misc
    ].index_by { |category| I18n.t("activerecord.attributes.service_request.categories.#{category}") }
  end

  private

  def create_janus_videoroom!
    return if Rails.env.test?
    return if janus_videoroom_pin

    pin = SecureRandom.hex
    return unless JanusApi.create_videoroom(id, pin)

    update(janus_videoroom_pin: pin)
  end
end
