class ReportWorker
  include Sidekiq::Worker
  require 'csv'
  require 'axlsx'
  require 'action_view'
  include ActionView::Helpers::NumberHelper
  sidekiq_options :queue => :default_report, :retry => false, :backtrace => true
  def perform(report_id,report_name,offset)
    rp = Report.find(report_id)  rescue return
    # from_time = rp.from_time.to_i
    # end_time = rp.to_time.to_i
    # from_time = (Time.zone.parse(rp.from_time.to_s).utc - (offset.to_i))
    # end_time = (Time.zone.parse(rp.to_time.to_s).utc - (offset.to_i))
    ln = rp.location_network
    ri = ln.router_inventories rescue return
    ri_name_mac = ri.inject({}){|h,v| h.merge({v.mac_id => v.name})}
    router_inventories_macids = ri.map(&:mac_id) rescue []
    uplinks_type_count = Uplink.unscoped.where('router_inventory_id in (?)',ri.pluck(:id)).order('uplink_type asc').pluck(:uplink_type).uniq
    ssids = ln.network_ssids.pluck(:id)
    #Initialize Aggregate query
    query = AggregateDataQuery.new([rp.from_time.to_date.to_s, rp.to_time.to_date.to_s], router_inventories_macids, [ln.id])
    aps_uplinks_usage = query.all_aps_uplinks_usage #if report_name.include?
    uplink_usage = {}
    if report_name.include?("Uplink Usage by AP")
      aps_uplinks_usage = query.all_aps_uplinks_usage #if report_name.include?
      (aps_uplinks_usage || []).each do |r|
        uplink_usage[r['_id']['mac']] = {} if uplink_usage[r['_id']['mac']].blank?
        uplink_usage[r['_id']['mac']][r['_id']['utype'].to_s] = {'tx' => r['tx'],'rx' => r['rx'],'total' => r['total']}
        uplink_usage[r['_id']['mac']]['ssid'] = RouterInventory.find_by_mac_id(r['_id']['mac']).get_associated_network_ssids.map(&:ssid_name).join(',') if uplink_usage[r['_id']['mac']]['ssid'].blank? && ln.id.to_s == '814'
      end
    end
    top_aps_usage = query.aps_total_usage(0, 5) if report_name.include?("Top 5 APs by Usage")
    top_clients_usage = query.clients_total_usage(0, 5) if report_name.include?("Top 5 Clients by Usage")
    usage_per_ssid = query.ssids_usage(ssids) if report_name.include?("Usage per SSID")
    no_of_clients_per_ssids = query.clients_count_per_ssids if report_name.include?("Number of connected Clients per SSID")
    no_of_clients = query.clients_count(true) if report_name.include?("Number of connected Clients")
    aps_in_network =  router_inventories_macids.inject({}) {|h,v| h.merge(v => {"version" => $redis.hget("AP:#{v}", "version")})} if report_name.include?("AP List")

    #top_aps_usage = ln.top_aps_usage(router_inventories_macids, from_time, end_time, "BYTES_INT").take(5) if report_name.include?("Top 5 APs by Usage")
    #top_clients_usage = ln.top_clients_usage(router_inventories_macids, from_time, end_time, "BYTES_INT").take(5) if report_name.include?("Top 5 Clients by Usage")
    #usage_per_ssid = ln.usage_per_ssid(router_inventories_macids, from_time, end_time) if report_name.include?("Usage per SSID")
    #no_of_clients_per_ssids = ln.no_of_clients_count_per_ssids(router_inventories_macids, from_time, end_time) if report_name.include?("Number of connected Clients per SSID")
    #no_of_clients = ln.no_of_clients_count_per_month(router_inventories_macids, from_time, end_time,offset) if report_name.include?("Number of connected Clients")
    ap_versions = []#ln.ap_versions(router_inventories_macids, from_time, end_time) if report_name.include?("AP List by Version")
    ap_geo_loc = []#ln.ap_geo_loc(router_inventories_macids, from_time, end_time) if report_name.include?("AP List by Geo Location")
    aps_down_time = query.get_aps_down_time(router_inventories_macids,ln) if report_name.include?("APs DownTime")
    RouterInventoryWorker.perform_async(ap_geo_loc) unless ap_geo_loc.blank?
    av = ActionView::Base.new()
    av.view_paths = ActionController::Base.view_paths
    av.class_eval do
            include Rails.application.routes.url_helpers
            include ApplicationHelper
    end
    pdf_path = Rails.root.join('public/reports', "Report-#{report_id}.pdf")
    if rp.download_type.try(:include?,"PDF")
      pdf_html = av.render :template => "reports/generate_pdf.html.erb", :layout => nil, :locals => {:top_aps_usage => top_aps_usage, :top_clients_usage=>top_clients_usage, :usage_per_ssid=>usage_per_ssid, :no_of_clients_per_ssids=>no_of_clients_per_ssids, :aps_in_network=>aps_in_network, :ap_versions=>ap_versions, :ap_geo_loc=>ap_geo_loc, :report_obj=>rp, :no_of_clients=>no_of_clients, :aps_down_time => aps_down_time,:aps_uplinks_usage => uplink_usage,:uplinks_type_count => uplinks_type_count,:ri_name_mac => ri_name_mac,:network => ln}
      doc_pdf = WickedPdf.new.pdf_from_string(pdf_html, :page_size => 'Letter')
      File.open(pdf_path, 'wb') { |file|    file << doc_pdf }
    end

    rp.update_attributes({:flag=>1,:path=>pdf_path.to_s})
  NotificationGroup.send_notification({object_id: rp.scheduled_report_id,type: "Report", report_id: rp.id}) if rp.try(:scheduled_report_id).present?
    #Creating CSV file for report
  if rp.download_type.try(:include?,"Excel")
    Axlsx::Package.new do |p|
      p.workbook.add_worksheet(:name => "AP Reports List") do |sheet|
        sheet.add_row ["Report Name : #{rp.title}"]
        sheet.add_row ["Network Name : #{rp.location_network.network_name}"]
        sheet.add_row ["Time Range : #{rp.from_time.strftime('%b %d %Y')+' to '+ rp.to_time.strftime('%b %d %Y')}"]
        sheet.add_row ["Created Time : #{Time.zone.parse(rp.created_at.to_s).in_time_zone(rp.location_network.timezone).strftime('%b %d %Y %H:%M:%S')}"]
        sheet.add_row [""]
        if top_aps_usage.present?
          sheet.add_row ["Top 5 APs by Usage"]
          sheet.add_row ["AP MAC","Down Stream","Up Stream","Total Usage"]
          (top_aps_usage || []).each do |x|
            val = ri_name_mac[x["_id"]].blank? ? x["_id"] : "#{ri_name_mac[x["_id"]]} (#{x["_id"].last(8)})"
            value_arr = []
            value_arr << val
            value_arr << number_to_human_size(x["rx"])
            value_arr << number_to_human_size(x["tx"])
            value_arr << number_to_human_size(x["total"])
            sheet.add_row value_arr
          end
        end
        
        if top_clients_usage.present?
          sheet.add_row [""]
          sheet.add_row ["Top 5 Clients by Usage"]
          sheet.add_row ["AP MAC","Down Stream","Up Stream","Total Usage"]
          (top_clients_usage || []).each do |x|
            val = ri_name_mac[x["_id"]].blank? ? x["_id"] : "#{ri_name_mac[x["_id"]]} (#{x["_id"].last(8)})"
            value_arr = []
            value_arr << val
            value_arr << number_to_human_size(x["rx"])
            value_arr << number_to_human_size(x["tx"])
            value_arr << number_to_human_size(x["total"])
            sheet.add_row value_arr
          end
        end

        if usage_per_ssid.present?
          sheet.add_row [""]
          sheet.add_row ["Usage per SSID"]
          sheet.add_row ["SSID Name","Down Stream","Up Stream","Total Usage"]
          (usage_per_ssid || []).each do |x|
            val = ri_name_mac[x["_id"]].blank? ? x["_id"] : "#{ri_name_mac[x["_id"]]} (#{x["_id"].last(8)})"
            value_arr = []
            value_arr << val
            value_arr << number_to_human_size(x["rx"])
            value_arr << number_to_human_size(x["tx"])
            value_arr << number_to_human_size(x["total"])
            sheet.add_row value_arr
          end
        end

        if no_of_clients_per_ssids.present?
          sheet.add_row [""]
          sheet.add_row ["Number of connected Clients per SSID"]
          sheet.add_row ["SSID Name","Clients","Percentage"]
          sum = 0
          (no_of_clients_per_ssids || []).each do |x|
            sum += x["count"]
          end
          (no_of_clients_per_ssids || []).each do |x|
            sheet.add_row [NetworkSsid.find_by_id(x["_id"]).try(:ssid_name)]
            count = x["count"]
            value_arr = []
            value_arr << count
            value_arr << ((count * 100)/sum).round(1)
            sheet.add_row value_arr
          end
        end

        if aps_in_network.present?
          sheet.add_row [""]
          sheet.add_row ["AP List"]
          sheet.add_row ["AP MAC","Version"]
          (aps_in_network || {}).each do |k, v|
            value_arr = []
            value_arr << ri_name_mac[k].blank? ? k : "#{ri_name_mac[k]} (#{k.last(8)})"
            value_arr << v["version"].gsub('"',"") if v["version"].present?
            sheet.add_row value_arr
          end
        end

        if ap_versions.present?
          sheet.add_row [""]
          sheet.add_row ["AP List by Version"]
          sheet.add_row ["AP MAC","Version"]
          (ap_versions || []).each do |x|
            val = ri_name_mac[x["_id"]["ap_mac"]].blank? ? x["_id"]["ap_mac"] : "#{ri_name_mac[x["_id"]["ap_mac"]]} (#{x["_id"]["ap_mac"].last(8)})"
            value_arr = []
            value_arr << val
            value_arr << x["version"].last.gsub('"',"") if x["version"].present?
            sheet.add_row value_arr
          end
        end

        if ap_geo_loc.present?
          sheet.add_row [""]
          sheet.add_row ["AP List by Geo Location"]
          sheet.add_row ["AP MAC","Address"]
          (ap_geo_loc || []).each do |x|
            val = @ri_name_mac[x["_id"]["ap_mac"]].blank? ? x["_id"]["ap_mac"] : "#{@ri_name_mac[x["_id"]["ap_mac"]]} (#{x["_id"]["ap_mac"].last(8)})"
            value_arr = []
            value_arr << val
            ri = RouterInventory.where(mac_id: x["_id"]["ap_mac"]).last
            value_arr << "#{ri.city}, #{ri.country}"
            sheet.add_row value_arr
          end
        end

        if no_of_clients.present?
          sheet.add_row [""]
          sheet.add_row ["Number of connected Clients (Clients count in below table has unique connected clients)"]
          sheet.add_row ["Date","Clients"]
          (no_of_clients || []).each do |x|
            value_arr = []
            value_arr << x["_id"]["d"].strftime("%Y-%m-%d")
            value_arr << x["count"]
            sheet.add_row value_arr
          end
        end
        if report_name.include?("Uplink Usage by AP")
          tot_downtime = 0
          row = []
          header = []
          col = []
          @tot = {}
          header = ["AP", "Name"]
          header << 'SSID' if ln.id.to_s == '814'
          (uplinks_type_count || []).each{ |i| header.push(["#{RouterInventory::UPLINK_TYPE[i]} Upstream", "#{RouterInventory::UPLINK_TYPE[i]} Downstream","#{RouterInventory::UPLINK_TYPE[i]} Total"])}
          sheet.add_row header.flatten
          uplink_usage.each do |key,val|
            row = [key,ri_name_mac[key] || '-']
            row << (val['ssid'] || '-') if ln.id.to_s == '814'
            (uplinks_type_count || []).each do |i|
              if val[i.to_s].present?
                row.push([number_to_human_size(val[i.to_s]['tx']),number_to_human_size(val[i.to_s]['rx']),number_to_human_size(val[i.to_s]['total'])])
                if @tot[i].blank?
                  @tot[i] = {}
                   @tot[i]['tx'] = 0
                   @tot[i]['rx'] = 0
                   @tot[i]['tot'] = 0
                end
                @tot[i]['tx'] += val[i.to_s]['tx']
                @tot[i]['rx'] += val[i.to_s]['rx']
                @tot[i]['tot'] += val[i.to_s]['total']
              else
                row.push(['-','-','-'])
              end
            end
              sheet.add_row row.flatten
          end
          row = ['TOTAL','']
          row << '' if ln.id.to_s == '814'
          (uplinks_type_count || []).each do |i|
           row.push([number_to_human_size(@tot[i]['tx']),number_to_human_size(@tot[i]['rx']),number_to_human_size(@tot[i]['tot'])]) unless @tot[i].blank?
          end
          sheet.add_row row.flatten
        end

        if aps_down_time.present?
          sheet.add_row [""]
          sheet.add_row ["AP Down time"]
          sheet.add_row ["Total Number of Aps: #{aps_down_time.count}"]
          @tot_downtime = @non_func_aps = 0
          aps_down_time.select{ |a| a["down_time"].select {|x| @non_func_aps += x['entire_period'] || 0}}
          sheet.add_row ["Number of Non-Functional Aps : #{@non_func_aps}"]
          sheet.add_row ["AP MAC","Tags","Downtime Period","Total Downtime"]
          aps_down_time.each do |x|
            value_arr = []
            @tot_downtime = 0 if !x['down_time'].blank?
            val = ri_name_mac[x["mac"]].blank? ? x["mac"] : "#{ri_name_mac[x["mac"]]} (#{x["mac"].last(8)})"
            value_arr << val
            value_arr << x["tags"].join(', ')
            (x["down_time"] || []).each do |list|
              unless  list['down_secs'].to_i == 0
                date = "#{Time.zone.parse(list['est'].to_s).in_time_zone(x['timezone']).strftime('%Y-%m-%d %H:%M:%S')} to #{Time.zone.parse(list['eet'].to_s).in_time_zone(x['timezone']).strftime('%Y-%m-%d %H:%M:%S')}"
                value_arr << date
                @tot_downtime += list['down_secs'].to_i
              end
            end
            value_arr << ApplicationController.helpers.time_converter(@tot_downtime)
            sheet.add_row value_arr
          end
        end
      end
      csv_path = Rails.root.join('public/reports', "Report-#{report_id}.xlsx")
      p.serialize(csv_path)
    end
  end
    if report_name.include?("Uplink Usage by AP")
      tot_downtime = 0
      row = []
      header = []
      col = []
      @tot = {}
      csv_path = Rails.root.join('public/reports', "Report-#{report_id}.csv")
      CSV.open(csv_path, "w",:headers => true) do |csv|
        csv <<  ["Report Name : #{rp.title}"]
        csv <<  ["Network Name : #{rp.location_network.network_name}"]
        csv <<  ["Time Range : #{rp.from_time.strftime('%b %d %Y')+' to '+ rp.to_time.strftime('%b %d %Y')}"]
        csv <<  ["Created Time : #{Time.zone.parse(rp.created_at.to_s).in_time_zone(rp.location_network.timezone).strftime('%b %d %Y %H:%M:%S')}"]
        csv <<  [""]
        header = ["AP", "Name"]
        header << 'SSID' if ln.id.to_s == '814'
        (uplinks_type_count || []).each{ |i| header.push(["#{RouterInventory::UPLINK_TYPE[i]} Upstream", "#{RouterInventory::UPLINK_TYPE[i]} Downstream","#{RouterInventory::UPLINK_TYPE[i]} Total"])}
        csv << header.flatten
        uplink_usage.each do |key,val|
          row = [key,ri_name_mac[key] || '-']
          row << (val['ssid'] || '-') if ln.id.to_s == '814'
          (uplinks_type_count || []).each do |i|
            if val[i.to_s].present?
              row.push([number_to_human_size(val[i.to_s]['tx']),number_to_human_size(val[i.to_s]['rx']),number_to_human_size(val[i.to_s]['total'])])
              if @tot[i].blank?
                @tot[i] = {}
                 @tot[i]['tx'] = 0
                 @tot[i]['rx'] = 0
                 @tot[i]['tot'] = 0
              end
              @tot[i]['tx'] += val[i.to_s]['tx']
              @tot[i]['rx'] += val[i.to_s]['rx']
              @tot[i]['tot'] += val[i.to_s]['total']
            else
              row.push(['-','-','-'])
            end
          end
            csv << row.flatten
        end
        row = ['TOTAL','']
        row << '' if ln.id.to_s == '814'
        (uplinks_type_count || []).each do |i|
         row.push([number_to_human_size(@tot[i]['tx']),number_to_human_size(@tot[i]['rx']),number_to_human_size(@tot[i]['tot'])]) unless @tot[i].blank?
        end
        csv << row.flatten
      end
    end
  end
end
