class UserSettingsController < ApplicationController
  wrap_parameters false

  def show
    return head :unauthorized unless current_user

    render json: current_setting.serializable_hash
  end

  def update
    return head :unauthorized unless current_user

    raw_attributes = editable_raw_attributes
    field_errors = validate_raw_attributes(raw_attributes)
    return render_validation_error fields: field_errors if field_errors.present?

    setting = current_setting
    setting.assign_attributes(raw_attributes)

    if setting.save
      render json: setting.serializable_hash, status: :ok
    else
      render_validation_error setting
    end
  end

  private

  def current_setting
    Setting.find_or_create_by!(user: current_user) do |setting|
      setting.assign_attributes(Setting.defaults)
    end
  rescue ActiveRecord::RecordNotUnique
    Setting.find_by!(user: current_user)
  end

  def editable_raw_attributes
    request.request_parameters.slice(*Setting::EDITABLE_ATTRIBUTES)
  end

  def validate_raw_attributes raw_attributes
    raw_attributes.each_with_object({ }) do |(key, value), errors|
      next if value_matches_type?(key, value)

      errors[key.to_sym] = ['値の型が不正です．']
    end
  end

  def value_matches_type? key, value
    case Setting::TYPE_BY_ATTRIBUTE.fetch(key)
    when :string
      value.is_a?(String)
    when :integer
      value.is_a?(Integer)
    when :boolean
      value == true || value == false
    else
      false
    end
  end
end
