class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  include PublicActivity::StoreController
  include PolicyCheck
  protect_from_forgery with: :exception, except: :options_method_cros, if: Proc.new { |c| c.request.format != 'application/json' }
  protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format == 'application/json' }
  before_action :configure_devise_permitted_parameters, if: :devise_controller?
  before_action :get_domain_user, except: [:esim_response, :options_method_cros]
  before_action :authenticate_user!, only: :become
  before_action :current_organisation, except: [:esim_response,:options_method_cros]
  before_action :validate_token, except: [:esim_response, :options_method_cros]
  after_action :set_response_header#, if: Proc.new {|c| c.request.format.json?}
  before_action :set_current_user_for_activity
  after_action :clear_current_user_for_activity
  alias_method :devise_current_user, :current_user
  rescue_from ActionController::UnknownFormat, with: :render_404
  include ApplicationHelper

  rescue_from CanCan::AccessDenied do |exception|
    respond_to do |format|
      format.json { render json: { error: "Requested resource is locked. You cannot do this operation." }, status: :forbidden }
      format.html { redirect_to root_url, :alert => exception.message }
    end
  end

  def get_domain_user
    current_org = Organisation.where("organisation_domain" => request.host).first
    if params[:user].present?
      if current_org.present?
        cur_user = current_org.users.where("email" => params[:user][:email]).first
        unless cur_user.present?
          redirect_to root_url
        end
      else
        cur_user = User.where("email" => params[:user][:email]).first
        if cur_user.present? && cur_user.organisation.branding
          redirect_to root_url
        end
      end
    end
  end

  def esim_response
    data = Uplink.esim_eid_response(params[:requestId]) unless params[:requestId].blank?
    render :json=> {:status=>true}
  end

  def sign_out_from_token_user
    session_instance = Session.find_by_id(session["session_instance_id"])
    session_instance.update_column("last_active_at",Time.now.utc) if session_instance.present?
    session["token"] = nil
    session["primary_user_id"] = nil if !params[:token].present?
    current_user
    redirect_to root_url
  end

  def render_404
    respond_to do |format|
    end
  rescue ActionController::UnknownFormat
    render status: 404, text: "Page Not Found"
  end

  def validate_token
    if session["token"].present?
      if check_token_validity(AssumeUserDetail.where(token: session[:token]).first)
        true
      else
        sign_out devise_current_user
      end
    else
      true
    end
  end

  def assume(user_id = nil)
    set_token_in_session if params[:token].present?
    redirect_to root_url
  end

  def become
    user = User.find_by_id(params[:id])
    if user.present? && current_user.is_super_admin
      session[:access_command] = true
      session[:assumes_upgrade_version] = true
      session[:assume_user] = current_user.id
      sign_in(:user, user, { :bypass => true })
    end
    assumed user
    redirect_to root_url # or user_root_url
  end

  def assumed user
    if session[:assume_user].present?
      parent_user = User.find_by_id(session[:assume_user])
      PublicActivity::Activity.create(trackable_id: user.id, trackable_type: "User", owner_id: user.id, owner_type: "User", key: "user.assumed", organisation_id: user.organisation_id, location_network_id: user.location_networks.present? ?user.location_networks.first.id : nil, parameters: {:attributes => {"user(#{user.email})" => {"assumed" => [nil,"#{parent_user.email}"]}}}, assumed_by: session[:assume_user])
    end
  end

  def tracked_current_user
    current_user
  end

  def user_assumed_by
    User.find_by_id(session[:assume_user]) if session[:assume_user].present?
  end

  def options_method_cros
    headers['Access-Control-Allow-Origin'] = '*'
    headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS, PUT, DELETE, PATCH'
    headers['Access-Control-Allow-Headers'] = 'content-type, X-Requested-With, X-Prototype-Version, X-USER-USERNAME, X-ACCESS-TOKEN, X-AUTH-TOKEN'
    headers['Access-Control-Max-Age'] = '1728000'

    render status: 200, nothing: true
  end


  protected

  def configure_devise_permitted_parameters
    registration_params = [:full_name, :email, :password, :password_confirmation, :phone_number, :company_name, :claimed_devices, :is_admin, :role_id]

    if params[:action] == 'update'
      devise_parameter_sanitizer.permit(:account_update, keys: registration_params + [:current_password])
    elsif params[:action] == 'create'
      devise_parameter_sanitizer.permit(:sign_up, keys: registration_params)
    end
  end

  def set_current_user_for_activity
    Thread.current[:current_user_id] = current_user.try(:id) if current_user.present?
  end

  def clear_current_user_for_activity
    Thread.current[:current_user_id] = nil
  end

  def dashboard_topbar
    logger.info("Current User <<<<<<<<<<<<<<<<<<<<<< #{current_user.email}")
  
    @location_networks = current_user.location_networks
                                     .select('DISTINCT ON (LOWER(LTRIM(network_name))) *')
                                    # .order('LOWER(LTRIM(network_name))')
    #commented order temporary
    @current_network = current_user.current_network
    logger.info("Current Network <<<<<<<<<<<<<<<<<<<<<< #{@current_network.id}") unless @current_network.blank?
  end

  def check_token_validity(assume_user_detail)
    if assume_user_detail.present? && assume_user_detail.status == true && (assume_user_detail.try(:token_validity) == 0 || (((Time.now.utc - assume_user_detail.try(:created_at)) / 1.hour).round <= assume_user_detail.try(:token_validity)))
      return true
    else
      return false
    end
  end

  def authenticate_user!
    if request.headers["X-AUTH-TOKEN"] || params["access_token"]
      access_token = request.headers["X-AUTH-TOKEN"].nil?  ?  params["access_token"] : request.headers["X-AUTH-TOKEN"]
      @user = User.where(:access_token => access_token).first
      if @user.present?
        @current_user = @user
      else
        @res_message = "Access denied! Invalid credentials"
        @res_status = 401
        @result = {}
       #   render 'configuration/create.json.jbuilder'
       render :json=> {:data=>@result,:message=>@res_message,:status=>@res_status}
      end
    else
      super
    end
  end

  def set_response_header
    headers['Access-Control-Allow-Origin'] = '*'
  end

    private

    def set_token_in_session
      session_instance = Session.create(email: current_user.email,logged_in_time: Time.now.utc,assume_user_detail_id: AssumeUserDetail.where(token: params[:token]).first.try(:id))
      session["session_instance_id"] = session_instance.id
      session["token"] = params[:token]
      session["primary_user_id"] = params[:id]
    end


  def current_user
    if session["primary_user_id"].blank?
      @current_user = devise_current_user
    else
      @current_user = User.find(session["primary_user_id"])
    end
  end

  def current_organisation
    @current_user = current_user
    domain_url = "#{request.host}"
    if @current_user.present?
      @current_organisation = @current_user.organisation 
    else
      @current_organisation = Organisation.where("organisation_domain" => domain_url).first
    end
    default_domain = APPLICATION[Rails.env]["default"]
    if domain_url != default_domain["domain"]
      if @current_organisation.present? && @current_organisation.branding
        @current_organisation
      else
        redirect_to "#{default_domain["protocol"]}://#{default_domain["domain"]}:#{default_domain["port"]}"
      end
    end
  end
  
  def check_network_presence?
    @current_user = @user if @user.present?
    @current_network = @current_user.location_networks.where(id: params[:network_id]).last if params[:network_id].present?
    @current_network = @current_user.location_networks.where(name: params[:network_name]).last if params[:network_name].present?
    if @current_network.blank?
      @res_message = "Network is not found. Please provide correct network id or network name"
      @res_status = 404
      @result = {}

      render :json => {:data => @result, :message => @res_message, :status => @res_status}, status: 404
    end
  end
 
end
