class DevicesController < ApplicationController
  # Device's `belongs_to :user` association enforces that only authenticated
  # users are able to register devices. This replaces the Authenticated Users
  # Pusher Beams solution.
  # See: https://github.com/forem/forem/pull/12419/files#r563906038
  skip_before_action :verify_authenticity_token, only: [:destroy]

  rescue_from ActiveRecord::ActiveRecordError, ArgumentError do |exc|
    render json: { error: exc.message, status: 422 }, status: :unprocessable_entity
  end

  def create
    device = Device.find_or_create_by(device_params)
    if device.persisted?
      # Even if the device ID may be irrelevant for the consumer, this
      # serves as confirmation that it was registered successfully.
      render json: { id: device.id }, status: :created
    else
      render json: { error: device.errors_as_sentence }, status: :bad_request
    end
  end

  def destroy
    device = Device.find_by(unauthenticated_params)
    unless device
      render json: { error: I18n.t("devices_controller.not_found"), status: 404 }, status: :not_found
      return
    end

    device.destroy
    if device.destroyed?
      head :no_content
    else
      render json: { error: device.errors_as_sentence }, status: :bad_request
    end
  end

  private

  def device_params
    {
      user: current_user,
      token: params[:token],
      platform: params[:platform],
      consumer_app: consumer_app
    }
  end

  # Unauthenticated params are used for `destroy` because in the mobile apps
  # we react to when a user "has logged out", meaning we no longer have the
  # `current_user` to validate ownership of the Device. In this case we
  # confirm the ownership if all the values from `unauthenticated_params`
  # match a Device. This is guaranteed because the PN token is unique per app
  # & device, i.e. only the real owner of the device is able to provide them.
  def unauthenticated_params
    {
      user_id: params[:id],
      token: params[:token],
      platform: params[:platform],
      consumer_app: consumer_app
    }
  end

  def consumer_app
    ConsumerApp.find_by(app_bundle: params[:app_bundle], platform: params[:platform])
  end
end
