class Admin::UsersController < AdminController
  include CacheExistence 
  before_filter :authenticate_user!,except: [:write_to_file]
  before_filter :dashboard_topbar,except: [:write_to_file]
  skip_before_filter :check_permission
  load_and_authorize_resource :class => User
  skip_load_resource :only => [:create,:user_setting,:update_user_setting,:get_current_user]
  skip_load_and_authorize_resource :only => [:write_to_file, :create, :get_network_permission, :user_profile_permission]
  
  
  def index
    if params[:ui] == "1"
      per_page = params[:per_page].to_i > 0 ? params[:per_page].to_i : 10
      sort_column = (params[:sort_column].presence || "full_name").to_s
      sort_direction = params[:sort_direction].presence || 'asc'
      selector_mode = params[:selector].present?
      org_id, current_user_id = current_user.organisation_id, current_user.id

      user_name = params[:user_name]
      user_id = params[:user_id]

      page = params[:page].to_i
      page = 1 if page < 1

      search_after = params[:search_after].present? ? JSON.parse(params[:search_after]) : nil
      if search_after.nil? && page > 1
        cached_token_key = "user_search:user_#{current_user_id}:page_#{page - 1}"
        search_after = Rails.cache.read(cached_token_key)
      end

      @total_count = nil
      total_cache_key = "network_search_total:user_#{current_user_id}"

      if params[:id].present? && !request.format.json?
        @user = current_user.organisation.users.not_machine_token_users.find_by_id(params[:id])
        unless @user
          flash[:warning] = 'User not found'
          redirect_to admin_users_path
          return
        end
      else
        @user = current_user.organisation.users.new
      end

      search_term =
        if params[:search].is_a?(Hash)
          params[:search][:value].to_s.strip
        elsif params[:search].is_a?(String)
          params[:search].strip
        else
          ""
        end

      if search_after.blank?
        @total_count = User.count_search_results(
          search_term,
          org_id,
          selector_mode,
          current_user.id,
          user_id,
          user_name
        )
        Rails.cache.write(total_cache_key, @total_count, expires_in: 30.minutes)
      else
        @total_count = Rails.cache.read(total_cache_key) || "unknown"
      end
      include_current_flag = params[:include_current].to_s == "true"

      search_result = User.search(
        search_term,
        sort_column,
        sort_direction,
        org_id,
        per_page,
        selector_mode,
        current_user.id,
        user_id,
        user_name,
        search_after,
        include_current_flag
      )
      @users = search_result.results

      total_count = @total_count || "unknown"
      has_more = search_result.has_more? rescue false
      next_search_after = search_result.next_search_after rescue nil

      if has_more && next_search_after.present?
        cache_key = "user_search:org_#{org_id}:page_#{page}"
        Rails.cache.write(cache_key, next_search_after, expires_in: 30.minutes)
      end

      next_page_token = has_more ? SecureRandom.uuid : nil

      return unless request.format.json?

      # Pagination metadata
      total_pages = total_count == "unknown" ? nil : (total_count.to_f / per_page).ceil
      pagination_meta = {
        current: page,
        previous: page > 1 ? page - 1 : nil,
        next: has_more ? page + 1 : nil,
        pages: total_pages,
        total: total_count
      }

      # Shared meta block
      base_meta = {
        page_token: params[:page_token],
        next_page_token: next_page_token,
        next_search_after: has_more ? next_search_after : nil,
        per_page: per_page,
        has_more: has_more,
        count: @users.size
      }.merge(pagination_meta)

      response_data = if selector_mode
        {
          data: {
            users: @users.map { |u| { id: u.id.to_i, full_name: u.full_name, email: u.email } }
          },
          meta: base_meta,
          status: 200
        }
      elsif params[:draw].present?
        {
          draw: params[:draw].to_i,
          recordsTotal: total_count == "unknown" ? @users.size : total_count,
          recordsFiltered: total_count == "unknown" ? @users.size : total_count,
          data: @users.map { |n| {
            id: n.id.to_i,
            full_name: n.full_name,
            email: n.email,
            role_name: n.role,
            network_access: n.network_access,
            has_role_admin: ["admin", "tier_2", "tier_3"].include?(n.role),
          }},
          meta: base_meta
        }
      else
        {
          data: {
            users: @users.map { |n| {
              id: n.id.to_i,
              full_name: n.full_name,
              user_email: n.email,
              phone_number: n.phone_number,
              company_name: n.company_name,
              organisation_id: n.organisation_id,
              confirmation_token: n.confirmation_token,
              role_id: n.role_id,
              approved: n.approved,
              access_token: n.access_token,
              authorized_networks: n.authorized_networks,
            }}
          },
          meta: base_meta,
          status: 200
        }
      end
      render json: response_data  
    else
      include_current = params[:include_current] == "true"

      @users =  if include_current
                  current_user.organisation.users.not_machine_token_users.includes(:role).where.not(is_admin: "true")
                else
                  current_user.organisation.users.not_machine_token_users.includes(:role).where.not(is_admin: "true") - [current_user]
                end

      if params[:id].present?
        @user = current_user.organisation.users.not_machine_token_users.find_by_id(params[:id])
        if @user.blank?
          flash[:warning] = 'User not found'
          redirect_to admin_users_path
        end
      else
        @user = current_user.organisation.users.new
      end
      if request.format.json?
        render json: {data: {users: @users.map(&:json_build)}}
      end
    end
  end

  def get_network_permission
    hash = {}
    change_network = params[:change_network]
    current_user.current_network = params[:network_id].to_i if change_network
    network_id = params[:network_id].to_i
    config_hash = User::CONFIG_HASH
    if network_id.present?
      if current_user.role.try(:name) == "network_admin"
        if current_user.networks_with_full_access.pluck(:id).include?(network_id)
          config_hash.keys.each { |key| hash[key] = 2 }
        elsif current_user.networks_with_limited_access.pluck(:id).include?(network_id)
          config_hash.keys.each { |key| hash[key] = 1 }  
        end
      else
        hash = user_profile_permission(true)
      end
    end
    render json: {data: {network_permissions: hash}}
  end

  def user_profile_permission netwk=false
    hsh1 = {
      email: current_user.email,
      full_name: current_user.full_name,
      phone: current_user.phone_number,
      role_name: current_user.role.name,
      access_token: current_user.access_token,
      is_super_admin: current_user.is_super_admin
    }   
    if current_user.current_network.present?
      hsh1[:current_network_name] = current_user.current_network.network_name
      hsh1[:current_network_id] = current_user.current_network.id
    end
    config_hash = User::CONFIG_HASH
    permission_hash = current_user.build_model_permission_hash(config_hash)
    if netwk
      return permission_hash
    end
    render json: {data: {user_details: hsh1, user_permissions: permission_hash}}
  end
  
  def create
    email = params['user']['email']
    if params["user"]["authorized_networks"].present?
      network_tags = {}
      network_tags["network_tags"] = params["user"]["authorized_networks"]
      user_params_dup = user_params.merge(network_tags)
      @user = current_user.organisation.users.build(user_params_dup)
    else
      @user = current_user.organisation.users.build(user_params)
    end
    @user.approved = true
    if @user.save
      index_doc = @user.as_indexed_json
      if index_doc["email"].blank? && email.present?
        index_doc["email"] = email
      end
      @user.__elasticsearch__.index_document(body: index_doc)
      flash.now[:success] = "User created Successfully"
      json_data = {data: @user.json_build , status: 200}
    else
      json_data = {message: "User is not created (Reason: #{@user.errors.full_messages}). Please check again.", status: 422}
      flash.now[:error] = "Oops! Problem in creating user"
      @users = current_user.organisation.users.includes(:role).where.not(is_admin: "true") - [current_user]
      # render :index
    end
    if request.format.json?
      render json: json_data, status: json_data[:status]
    else
      redirect_to admin_users_path
    end
  end

  def update
    @user = current_user.organisation.users.not_machine_token_users.find_by_id(params[:id])
    if @user.present?
      if params["user"]["authorized_networks"].present?
        network_tags = {}
        network_tags["network_tags"] = params["user"]["authorized_networks"]
        user_params_dup = user_params.merge(network_tags)
        if user_params_dup[:password].blank? && user_params_dup[:password_confirmation].blank?
          status = @user.update_without_password user_params_dup
        else
          status = @user.update user_params_dup
        end
      else
        if user_params[:password].blank? && user_params[:password_confirmation].blank?
          status = @user.update_without_password user_params
        else
          status = @user.update user_params
        end
      end
      if status
        flash[:success] = "User updated Successfully"
        json_data = {data: @user.json_build , status: 200}
      else
        flash[:error] = "Oops! Problem in user update"
        json_data = {message: "User is not updated (Reason: #{@user.errors.full_messages}).", status: 422}
        @users = current_user.organisation.users.not_machine_token_users.includes(:role).where.not(is_admin: "true") - [current_user]
      end
    else
      flash[:success] = "User not found"
      json_data = {message: 'User not found' , status: 404}
    end
    if request.format.json?
      render json: json_data, status: json_data[:status]
    else
      redirect_to admin_users_path
    end
  end

  def get_current_user
    if request.format.json?
      render json: {data: current_user.json_build, status: 200}
    end
  end

  def show
    @user = current_user.organisation.users.not_machine_token_users.find_by_id(params[:id])
    if request.format.json?
      #@user = current_user.organisation.users.find(params[:id])
      render json: {data: @user.json_build, status: 200}
    end
  end

  def destroy
    @user = current_user.organisation.users.not_machine_token_users.find_by_id(params[:id])

    if @user.blank?
      flash[:warning] = "User Not Found"
      json_data = {message: "User not found", status: 404}
    elsif @user.destroy
      flash[:success] = "User deleted Successfully"
      json_data = {data: {}, status: 200}
    else
      flash[:error] = "Oops! Problem in user delete"
      json_data = {message: "User is not deleted. Please try again." , status: 422}
    end
    if request.format.json?
      render json: json_data, status: json_data[:status]
    else
      redirect_to admin_users_path
    end
  end

   def email_exist
    render :json=>{:status=>true} and return if params[:email].blank?
    new_user = User.where(email: params[:email]).first if params[:user_id].blank?
    unless params[:user_id].blank?
      existing_user = User.where(email: params[:email],id: params[:user_id]).first
      change_user_email = User.where(email: params[:email]).first
    end
    render :json=>{:status=>false} and return if(new_user.present?)
    render :json=>{:status=>true} and return if(new_user.blank? && params[:user_id].blank?)
    render :json=>{:status=>false} and return if(existing_user.blank? && change_user_email.present?)
    render :json=>{:status=>true} and return if(existing_user.blank? && change_user_email.blank?)
    render :json=>{:status=>true} and return if(existing_user.id == change_user_email.id)
  end

  def user_setting
    @user = User.new
  end

  def update_user_setting
    if current_user.valid_password?(params[:user][:current_password])
      if params[:user][:password].eql?params[:user][:password_confirmation]
        flash[:success] = "Your Password has been updated!" if current_user.update_attribute(:password ,params[:user][:password])
        UserMailer.delay.password_changed(current_user.id)
        sign_in current_user, :bypass => true
      else
        flash[:notice]= "Sorry! New Passowrd and Confirmation password does not match, please try again"
      end
    else
      flash[:notice] = "Sorry! Current Passowrd is not valid, please try again"
    end
    redirect_to user_setting_admin_users_path
  end

  def write_to_file
   puts "writing in the file"
   f_path =  Rails.root.join("public/temp_file/temp_file.txt")
      Dir.mkdir(Rails.root.join("public/temp_file")) unless Dir.exist?(Rails.root.join("public/temp_file"))
      #temp_file = Tempfile.new("temp_file")
      File.open(f_path, 'a') do |file|
          file.write("\n")
          file.write(params[:input])
      end
      #temp_file.rewind
      #FileUtils.cp(temp_file.path, f_path)
      FileUtils.chmod 0755, "#{f_path}"
      #temp_file.unlink
       render :json=>{:status=>true,:msg => 'Successfully wrote data to file'}
  end

  private

  def current_ability
    if cache_exist?
      @current_ability ||= Ability::UserAbility.new(current_user)
    else
      @current_ability ||= Ability.new(current_user)
    end
  end

  def user_params
    params.require(:user).permit(:full_name, :email, :password, :password_confirmation, :phone_number, :role_id, :network_tags, :tag_list ,:authorized_networks => [:full => [], :limited => []])
  end
end
