class ActivityLogController < ApplicationController
  include CacheExistence
  before_filter :authenticate_user!
  load_and_authorize_resource :class => PublicActivity::Activity
  skip_load_resource :only => [:index, :list_activity]
  include ActivityLogHelper

  def index
    @startDate = 6.days.ago
    @endDate = 0.days.ago
    # @user = current_user.is_admin == "true" || current_user.role.name == "admin" ? current_user.organisation.users - [current_user] : []
    #@log = PublicActivity::Activity.where(owner_id: current_user.id,created_at: @startDate..@endDate).order("created_at desc").page(1).per(10)
  end

  def list_activity
    @startDate = params[:start_date] || 6.days.ago
    @endDate = params[:end_date] || 0.day.ago
    page = params[:page] || 1

    if params[:network_id] == '0'
      permitted_network_ids = current_user.permitted_networks.pluck(:id)
      if current_user.is_admin == "true" || current_user.role.name == "admin" || current_user.is_tier_2? || current_user.is_tier_3?
        network = {}
      else
        if ['login', 'logout'].include?(params[:activity])
          network = {}
        elsif params[:activity_type] == '0'
          network = {location_network_id: [permitted_network_ids, nil].flatten}
        else
          network = {location_network_id: permitted_network_ids}
        end
      end
    else
       network = {location_network_id: params[:network_id]} 
    end
    user = params[:user_id] == '0' ? (current_user.is_admin == "true"  || current_user.role.name == "admin") ? {} : {owner_id: current_user.id}: {owner_id: params[:user_id]}
    condition =  current_user.is_admin == true && !params[:organisation_id].blank? ? {organisation_id: params[:organisation_id],created_at: @startDate.to_datetime..@endDate.to_datetime} : {organisation_id: current_user.organisation_id,created_at: @startDate.to_datetime..@endDate.to_datetime}
    params[:activity] = params[:activity].split(',') if params[:activity] != "null"
    activity = (params[:activity_type].present? && !params[:activity].include?('null') && !params[:activity].include?('0')) ? {trackable_type: params[:activity].map {|activity| activity.split('_').map(&:capitalize).join('')}} : {}#params[:activity].split('_').map(&:capitalize).join('')} : {}
    activity_type = !params[:activity].include?('0') && params[:activity_type] != '0' ? {key: [params[:activity],params[:activity_type]].join('.')} : {}
    activity_type = "activities.key LIKE '%.#{params[:activity_type]}%'" unless params[:activity_type] == '0'
    act_type = []
    act_type << activity_type if activity_type.present?
    unless activity.empty?
      activity[:trackable_type] += ["AlertRule"] if activity[:trackable_type].include?("Alert")
      activity[:trackable_type] += ["AccessControlList"] if activity[:trackable_type].include?("AclGroup")
      activity[:trackable_type] += ["SwitchPortConfiguration"] if activity[:trackable_type].include?("SwitchConfiguration")
      activity[:trackable_type] += ["RadioSetting"] if activity[:trackable_type].include?("RadioProfile")
      if activity[:trackable_type].include?("Login")
        idx = activity[:trackable_type].index('Login')
        activity[:trackable_type][idx] = "User"
      end  
      if activity[:trackable_type].include?("Logout")
        idx = activity[:trackable_type].index('Logout')
        activity[:trackable_type][idx] = "User"
      end
      activity[:trackable_type] = activity[:trackable_type].uniq
    end
    if !params[:activity].include?('0') && params[:activity].include?('login')
      act_type << "activities.key LIKE '%.#{"login"}'"
    end
    if !params[:activity].include?('0') && params[:activity].include?('logout')
      act_type << "activities.key LIKE '%.#{"logout"}'"
    end
    if act_type.length > 0 && params[:activity_type] == '0'
      trackable_types = activity[:trackable_type] - ['User']
      if trackable_types.present?
        trackable_types.each do |key|
          act_type << "activities.key LIKE '#{key.underscore}.%'"
        end
      end
    end
    if act_type.length > 0 && act_type.length == 1
      activity_type = act_type.first
    elsif act_type.length > 1
      activity_type = act_type.join(" OR ")
    end

    @logs = PublicActivity::Activity.where(condition.merge(network).merge(user).merge(activity)).where(activity_type).order("created_at desc")
    
    @log = @logs.page(page).per(10)
    if request.format.json?
      render json: {data: {activity_logs: activity_log_api(@log)},meta:{current_page:@log.current_page,next_page:@log.next_page,prev_page:@log.prev_page,total_pages:@log.total_pages,total_count:@log.total_count}}
    else
      respond_to do |format|
        format.html { render layout: false }

        format.csv do
          if @logs.blank? || @logs.empty?
            head :no_content # return 204 No Content if no logs
            next
          end
          
          filename = "activity_log_#{Time.now.to_i}.csv"
          headers['Content-Disposition'] = "attachment; filename=\"#{filename}\""
          headers['Content-Type'] ||= 'text/csv'
          headers['Cache-Control'] = 'no-cache'
          headers['X-Accel-Buffering'] = 'no'

          self.response_body = Enumerator.new do |yielder|
            yielder << "Performed_By,Performed_At,Activity_Type,Activity_On,Old,New\n"

            activity_log_api(@logs).each do |doc|
              old_description, new_description = "", ""

              if doc['activity_description'].present?
                changes_on = doc['activity_description']['changes_on']
                changed_values = doc['activity_description']['changed_values']

                old_description = changes_on.to_s + "\n" if changes_on.present?
                new_description = changes_on.to_s + "\n" if changes_on.present?

                if changed_values.present?
                  changed_values.each do |key, value|
                    from_val = value[0] rescue ""
                    to_val = value[1] rescue ""
                      old_description += (from_val.present? ? "#{key}: #{from_val}\n" : "#{key}: nil\n")
                      new_description += (to_val.present? ? "#{key}: #{to_val}\n" : "#{key}: nil\n")
                  end
                elsif doc['activity_type'].include?('destroy')
                  new_description += "#{changes_on.split('(').last.split(')').first} has been deleted"
                elsif doc['activity_type'].present? && doc['activity_type'].include?('update') && changed_values.blank?
                  new_description += "Configuration has been resaved"
                end
              end

              row = [
                      escape_csv(doc['activity_performed_by']),
                      escape_csv(doc['activity_performed_at']),
                      escape_csv(doc['activity_type']),
                      escape_csv(doc['activity_on']),
                      escape_csv(old_description.present? ? old_description.strip : old_description),
                      escape_csv(new_description.present? ? new_description.strip : new_description)
                    ].join(',')

              yielder << row + "\n" if row.present?
            end
          end
        end
      end
    end
  end

  def activity_log_api(log_val)
    log_activities = []
    (log_val || []).each do |log|
      hsh = {}
      unless (log.parameters[:attributes].try(:keys).try(:first) == "v_lan(0)")
        attribute_hash = log.parameters[:attributes].try(:values).try(:first)
        if (attribute_hash && attribute_hash.keys.include?("last_sign_in_at"))
          log.trackable.user_type == nil ? hsh["activity_type"] = "login (via web)" : hsh["activity_type"] = "login (via saml)"
        else
          hsh["activity_type"] = log.key.split('.')[1]
        end
        hsh["activity_performed_by"] = activity_user(log)
        hsh["activity_performed_at"] = log.created_at.strftime("%d %B %Y - %H:%M (UTC)")
        hsh["activity_on"] = Organisation::MODEL_NAME_MAP[log.trackable_type.split(".")[0]] || log.trackable_type.split(".")[0]
        hsh["network"] = LocationNetwork.find_by_id(log.location_network_id).try(:network_name)
        hsh["network_id"] = LocationNetwork.find_by_id(log.location_network_id).try(:id)
        hsh["activity_description"] = ActivityLog.activity_description(log) 
      end
      log_activities << hsh
    end
    log_activities
  end

  def change_network
    network = current_user.location_networks.find_by_id(params[:id])
    unless network.present?
      network = current_user.location_networks.first
      flash[:notice] = "Your network has been changed to #{network.network_name}"
    end
    current_user.current_network = network.id
    @current_network = current_user.current_network
    logger.info("Current Network in show <<<<<<#{@current_network.id}") unless @current_network.blank?
    redirect_to "/home/#{params[:id]}"
  end

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

  def escape_csv(value)
    "\"#{value.to_s.gsub('"', '""')}\""
  end
end
