class ApplicationController < ActionController::API
  before_action :authenticate_request!
  before_action :enforce_password_reset!, unless: :support_token?
  before_action :enforce_terms_of_service_agreement!, unless: :support_token?

  around_action :set_time_zone, if: :current_user

  include ResponseMethods
  include ApplicationHelper

  private
    def authenticate_request!
      return if validate_api_key && user_token&.validate_token(headers['access-token']) &&
        current_school.active? && current_user.is_active?

      render_error :forbidden, errors: 'Not Authenticated'
    end

    def enforce_password_reset!
      return unless current_user.password_alert?

      render_error :password_reset, errors: 'Password change required'
    end

    def enforce_terms_of_service_agreement!
      return if current_user.accepted_terms_of_service?

      render_error :accept_terms, errors: 'Terms of Service must be accepted'
    end

    def current_user(id=nil)
      @current_user ||= User.find_by(id: id || headers['uid'])
    end

    def user_token
      @user_token ||= Token.find_by(user: current_user, client: headers['client'])
    end

    def headers
      request.headers
    end

    def validate_api_key
      headers['key'] == Rails.application.secrets.internal_api_key
    end

    def refresh_token
      return if user_token.is_batch? || user_token.reuse_token?

      user_token.with_lock do
        user_token.refresh

        response.headers.merge!(user_token.auth_headers) if user_token.save
      end
    end

    def current_school
      @current_school ||= current_user&.school
    end

    def current_school_year
      @current_school_year ||= current_school.school_years.current
    end

    def role
      current_user.role
    end

    def scoped_role
      case role
      when :family
        current_user.family
      when :student
        current_user.student
      else
        Employee.find(current_user.id)
      end
    end

    def grade_levels
      @grade_levels ||= current_school.grades_hash
    end

    def set_time_zone(&block)
      Time.use_zone(current_school.time_zone, &block)
    end

    def support_token?
      user_token&.support_user_id?
    end
end
