# frozen_string_literal: true

module Api
  module V1
    class SessionsController < ::Api::BaseController
      skip_authorization_check except: [:confirm_access]
      before_action :authenticate_user!, except: [:create]

      def create
        resource = User.find_for_database_authentication(login: login_params[:login])

        if resource.blank?
          render json: {code: "session.create.not_found_in_database", message: I18n.t("devise.failure.not_found_in_database")}, status: :bad_request
          return
        else
          unless resource.active_for_authentication?
            resource.resend_confirmation

            render json: {code: "session.create.unconfirmed", message: I18n.t("devise.failure.unconfirmed")}, status: :bad_request
            return
          end

          if resource.otp_required_for_login && two_factor_code.blank?
            render json: {code: "session.create.two_factor_required", message: I18n.t("devise.failure.two_factor_required")}, status: :bad_request
            return
          end

          unless resource.valid_password?(login_params[:password])
            render json: {code: "session.create.invalid", message: I18n.t("devise.failure.not_found_in_database")}, status: :bad_request
            return
          end

          if resource.otp_required_for_login && !resource.validate_and_consume_otp!(two_factor_code)
            if resource.invalidate_otp_backup_code!(two_factor_code)
              resource.save!
            else
              render json: {code: "session.create.invalid", message: I18n.t("devise.failure.two_factor_invalid")}, status: :bad_request
              return
            end
          end
        end

        resource.remember_me = remember_me

        sign_in(:user, resource)

        render json: {code: :success, message: I18n.t("labels.success")}
      end

      def destroy
        sign_out(:user)

        render json: {code: "sessions.destroy", message: I18n.t("devise.sessions.signed_out")}
      end

      def confirm_access
        authorize! :confirm_access, current_user

        unless current_user.valid_password?(login_params[:password])
          render json: {code: "session.confirmAccess.failure", message: I18n.t("messages.confirmAccess.failure")}, status: :bad_request
          return
        end

        cookies.encrypted["#{Rails.configuration.cookie_prefix}_ACCESS_CONFIRMED"] = {
          value: current_user.confirm_access_token,
          domain: Rails.configuration.app.cookie_domain,
          secure: Rails.env.production? || Rails.env.staging?,
          expires: 15.minutes,
          httponly: true,
          same_site: :lax
        }

        render json: {code: :success, message: I18n.t("labels.success")}
      end

      private def user_agent
        @user_agent ||= UserAgent.parse(request.user_agent)
      end

      private def login_params
        @login_params ||= params.permit(:login, :password, :remember_me, :two_factor_code, :rememberMe, :twoFactorCode)
      end

      private def remember_me
        login_params[:remember_me] || login_params[:rememberMe]
      end

      private def two_factor_code
        login_params[:two_factor_code] || login_params[:twoFactorCode]
      end

      private def invalid_login_attempt
        render json: {code: "session.create", message: I18n.t("devise.failure.invalid")}, status: :bad_request
      end
    end
  end
end
