class UserController < ApplicationController
  before_action :authenticate_user!, only: %w[edit update edit_privacy update_privacy data export begin_export edit_security update_2fa destroy_2fa reset_user_recovery_codes edit_mute]

  def show
    @user = User.where('LOWER(screen_name) = ?', params[:username].downcase).includes(:profile).first!
    @answers = @user.cursored_answers(last_id: params[:last_id])
    @answers_last_id = @answers.map(&:id).min
    @more_data_available = !@user.cursored_answers(last_id: @answers_last_id, size: 1).count.zero?

    if user_signed_in?
      notif = Notification.where(target_type: "Relationship", target_id: @user.active_follow_relationships.where(target_id: current_user.id).pluck(:id), recipient_id: current_user.id, new: true).first
      unless notif.nil?
        notif.new = false
        notif.save
      end
    end

    respond_to do |format|
      format.html
      format.js { render layout: false }
    end
  end

  # region Account settings
  def edit
  end

  def update
    user_attributes = params.require(:user).permit(:show_foreign_themes, :profile_picture_x, :profile_picture_y, :profile_picture_w, :profile_picture_h,
                                                   :profile_header_x, :profile_header_y, :profile_header_w, :profile_header_h, :profile_picture, :profile_header)
    if current_user.update(user_attributes)
      text = t(".success")
      text += t(".notice.profile_picture") if user_attributes[:profile_picture]
      text += t(".notice.profile_header") if user_attributes[:profile_header]
      flash[:success] = text
    else
      flash[:error] = t(".error")
    end
    redirect_to edit_user_profile_path
  end

  def update_profile
    profile_attributes = params.require(:profile).permit(:display_name, :motivation_header, :website, :location, :description, :anon_display_name)

    if current_user.profile.update(profile_attributes)
      flash[:success] = t(".success")
    else
      flash[:error] = t(".error")
    end
    redirect_to edit_user_profile_path
  end
  # endregion

  # region Privacy settings
  def edit_privacy
  end

  def update_privacy
    user_attributes = params.require(:user).permit(:privacy_allow_anonymous_questions,
                                                   :privacy_allow_public_timeline,
                                                   :privacy_allow_stranger_answers,
                                                   :privacy_show_in_search)
    if current_user.update(user_attributes)
      flash[:success] = t(".success")
    else
      flash[:error] = t(".error")
    end
    redirect_to edit_user_privacy_path
  end
  # endregion

  def followers
    @title = 'Followers'
    @user = User.where('LOWER(screen_name) = ?', params[:username].downcase).includes(:profile).first!
    @relationships = @user.cursored_follower_relationships(last_id: params[:last_id])
    @relationships_last_id = @relationships.map(&:id).min
    @more_data_available = !@user.cursored_follower_relationships(last_id: @relationships_last_id, size: 1).count.zero?
    @users = @relationships.map(&:source)
    @type = :friend

    respond_to do |format|
      format.html { render "show_follow" }
      format.js { render "show_follow", layout: false }
    end
  end

  # rubocop:disable Metrics/AbcSize
  def followings
    @title = 'Following'
    @user = User.where('LOWER(screen_name) = ?', params[:username].downcase).includes(:profile).first!
    @relationships = @user.cursored_following_relationships(last_id: params[:last_id])
    @relationships_last_id = @relationships.map(&:id).min
    @more_data_available = !@user.cursored_following_relationships(last_id: @relationships_last_id, size: 1).count.zero?
    @users = @relationships.map(&:target)
    @type = :friend

    respond_to do |format|
      format.html { render "show_follow" }
      format.js { render "show_follow", layout: false }
    end
  end
  # rubocop:enable Metrics/AbcSize

  def questions
    @title = 'Questions'
    @user = User.where('LOWER(screen_name) = ?', params[:username].downcase).includes(:profile).first!
    @questions = @user.cursored_questions(author_is_anonymous: false, last_id: params[:last_id])
    @questions_last_id = @questions.map(&:id).min
    @more_data_available = !@user.cursored_questions(author_is_anonymous: false, last_id: @questions_last_id, size: 1).count.zero?

    respond_to do |format|
      format.html
      format.js { render layout: false }
    end
  end

  def data
  end

  def export
    if current_user.export_processing
      flash[:info] = t(".info")
    end
  end

  def begin_export
    if current_user.can_export?
      ExportWorker.perform_async(current_user.id)
      flash[:success] = t(".success")
    else
      flash[:error] = t(".error")
    end

    redirect_to user_export_path
  end

  def edit_security
    if current_user.otp_module_disabled?
      current_user.otp_secret_key = User.otp_random_secret(25)
      current_user.save

      qr_code = RQRCode::QRCode.new(current_user.provisioning_uri("Retrospring:#{current_user.screen_name}", issuer: "Retrospring"))

      @qr_svg = qr_code.as_svg({ offset: 4, module_size: 4, color: "000;fill:var(--primary)" }).html_safe
    else
      @recovery_code_count = current_user.totp_recovery_codes.count
    end
  end

  def update_2fa
    req_params = params.require(:user).permit(:otp_validation)
    current_user.otp_module = :enabled

    if current_user.authenticate_otp(req_params[:otp_validation], drift: APP_CONFIG.fetch(:otp_drift_period, 30).to_i)
      @recovery_keys = TotpRecoveryCode.generate_for(current_user)
      current_user.save!

      render "settings/security/recovery_keys"
    else
      flash[:error] = t(".error")
      redirect_to edit_user_security_path
    end
  end

  def destroy_2fa
    current_user.otp_module = :disabled
    current_user.save!
    current_user.totp_recovery_codes.delete_all
    flash[:success] = t(".success")
    redirect_to edit_user_security_path
  end

  def reset_user_recovery_codes
    current_user.totp_recovery_codes.delete_all
    @recovery_keys = TotpRecoveryCode.generate_for(current_user)
    render 'settings/security/recovery_keys'
  end

  # region Muting
  def edit_mute
    @rules = MuteRule.where(user: current_user)
  end
  # endregion

  def edit_blocks
    @blocks = Relationships::Block.where(source: current_user)
    @anonymous_blocks = AnonymousBlock.where(user: current_user)
  end
end