class HeartbeatWorker
  include Sidekiq::Worker
  sidekiq_options :queue => :monitoring, :retry => false, :backtrace => true

  def perform(message)
    if message.is_a?(String) && message == "true"
      message = $redis.lpop('bravo')
      message = JSON.parse(message)
    end
    unless message.blank?
      #p message
      #Add data to monitoring capped collection
      nasid = message["INFO"]["NASID"]
      ap_details = $redis.hgetall "AP:#{nasid}"
      message['ln_id'] = ap_details['ln_id']
      message['org_id'] = ap_details['org_id']
      MonitoringDataCapped.save_hb(message.deep_dup)

      mc = MonitoringChild.save_hb(message.deep_dup)

      last_hb = ap_details["last_hb"]
      last_uptime_real = ap_details['last_uptime']
      config_update = false

      cl_wired = 0  
      cl_24 = 0 
      cl_5 = 0        
      (mc.clients || []).each do |client|
        if client["TYPE"].to_i == 1
          cl_wired += 1
        elsif client["TYPE"].to_i == 2
          if client['BD'].to_i == 1
            cl_24 += 1
          elsif client['BD'].to_i == 2
            cl_5 += 1
          end
        end
      end

      if mc.info["FIRST_HB"] == 1
        hb_freq = ap_details['hb_freq']
        interval = (ap_details['hb_down_interval'] || RouterInventory.get_hb_intreval(hb_freq)).to_i
        if message['ap_down_time']
          if last_hb.present? && message['ap_down_time']['sec'].present? && message['ap_down_time']['sec'] >= interval
            record_ap_downtime(mc.info['NASID'], message['ap_down_time'], false)
          elsif last_uptime_real.present? && mc.s_info.present? && last_uptime_real.to_i > mc.s_info['UPTIME_REAL'].to_i
            record_ap_downtime(mc.info['NASID'], message['ap_down_time'], true)
          end
        end

        version=mc.info["PIAP_VERSION"]
        if (ap_details["version"].blank? && (version.present? && version.gsub('.','').to_i <= 20222)) || (ap_details["version"].present? && ap_details["version"].gsub('.','').to_i <= 20222 && version.present? && version.gsub('.','').to_i > 20222)
          config_update = true#RouterInventory.where(mac_id: mc.info['NASID']).last.try(:update_redis)
        end
        #Trigger init commands for Spoton devices
        InitCommandWorker.perform_async(mc.info['NASID'], ap_details)
      end
      #Set redis last HB time
      # ap_details = $redis.hgetall "AP:#{mc.info['NASID']}"

      current_active_uplink = ""
      current_active_uplink_type = ""
      
      if ap_details['hw_type'] == 'router'
        active_uplinks = JSON.parse(ap_details['uplinks'] || '{}')
        active_uplink_count = 0

        
        mc.uplink.each do |uplink|
          if uplink['IS'] == 1 && active_uplinks.key?(uplink['UID'])
            active_uplinks[uplink['UID']]['status'] = "active"
            active_uplinks[uplink['UID']]['signal'] = uplink['SIG']
            current_active_uplink = uplink['UID']
            current_active_uplink_type = active_uplinks[uplink['UID']]['type']
            active_uplink_count += 1
          elsif uplink['IS'] == 3 && active_uplinks.key?(uplink['UID'])
            active_uplinks[uplink['UID']]['status'] = 'blocked'
          elsif active_uplinks.key?(uplink['UID'])
            active_uplinks[uplink['UID']]['status'] = "down"
          end
        end
      
        if active_uplink_count > 1
          mc.uplink.each do |uplink|
            if uplink['IS'] == 1 && active_uplinks[uplink['UID']]['is_primary']
              current_active_uplink = uplink['UID']
              current_active_uplink_type = active_uplinks[uplink['UID']]['type']
            end
          end
        end
      end
            
      curr_ap_details = []
      if message['created_at'].blank?
        curr_ap_details += ["prev_last_hb", last_hb] 
        curr_ap_details += ["last_hb", mc.created_at.to_i] 
      end
      curr_ap_details += ["last_uptime", mc.s_info['UPTIME_REAL'].to_i] unless mc.s_info.blank?

      firmware_changed = false
      bn_changed = false
      # ip_changed = false

      if mc.info["PIAP_VERSION"].present? && (ap_details["version"].blank? || ap_details["version"] != mc.info["PIAP_VERSION"] || mc.info["FIRST_HB"] == 1)
        curr_ap_details += ["version", mc.info["PIAP_VERSION"]]
        firmware_changed = true if mc.info["PIAP_VERSION"] != ap_details["version"]
      end

      if mc.info["BN"].present? && (ap_details["BN"].blank? || ap_details["BN"] != mc.info["BN"] || mc.info["FIRST_HB"] == 1)
        curr_ap_details += ["BN", mc.info["BN"]]
        bn_changed = true if mc.info["BN"] != ap_details["BN"]
      end

      if mc.info["BNM"].present? && (ap_details["BNM"].blank? || ap_details["BNM"] != mc.info["BNM"] || mc.info["FIRST_HB"] == 1)
        curr_ap_details += ["BNM", mc.info["BNM"]]
      end

      curr_ap_details += ["p_version", ap_details["version"]] if ap_details["version"] != mc.info["PIAP_VERSION"] && mc.info["FIRST_HB"] == 1

      if mc.s_info.present? && mc.s_info["PUBLIC_IP"].present? && (ap_details["pub_ip"].blank? || ap_details["pub_ip"] != mc.s_info["PUBLIC_IP"] || mc.info["FIRST_HB"] == 1)
        curr_ap_details += ["pub_ip", mc.s_info["PUBLIC_IP"]]
        # ip_changed = true 
      end

      curr_ap_details += ["CL_W", cl_wired]
      curr_ap_details += ["CL_24", cl_24]
      curr_ap_details += ["CL_5", cl_5]
      if ap_details['hw_type'] == 'router'
        curr_ap_details += ["active_uplinks", active_uplinks.to_json]
        curr_ap_details += ["curr_active_uplink", current_active_uplink]
        curr_ap_details += ["curr_active_uplink_type", current_active_uplink_type]
      end
      # $redis.hset "AP:#{mc.info['NASID']}", "prev_last_hb", last_hb
      # $redis.hset "AP:#{mc.info['NASID']}", "last_hb", mc.created_at.to_i
      # $redis.hset "AP:#{mc.info['NASID']}", "version", mc.info["PIAP_VERSION"] if ap_details["version"].blank? || ap_details["version"] != mc.info["PIAP_VERSION"] || mc.info["FIRST_HB"] == 1
      # $redis.hset "AP:#{mc.info['NASID']}", "p_version", ap_details["version"] if ap_details["version"] != mc.info["PIAP_VERSION"] && mc.info["FIRST_HB"] == 1
      # $redis.hset "AP:#{mc.info['NASID']}", "pub_ip", mc.s_info["PUBLIC_IP"] if ap_details["pub_ip"].blank? || (mc.s_info.present? && ap_details["pub_ip"] != mc.s_info["PUBLIC_IP"])  || mc.info["FIRST_HB"] == 1
      if mc.radio != nil
        mc.radio.each do |radio|
          if radio['BD'].to_s == '1'
            curr_ap_details += ["C_24GHZ" , radio['CH']]
            curr_ap_details += ["P_24GHZ" , radio['TXP']]
            # $redis.hset "AP:#{mc.info['NASID']}", "C_24GHZ" , radio['CHANNEL']
            # $redis.hset "AP:#{mc.info['NASID']}", "P_24GHZ" , radio['TXPOWER']
          else
            curr_ap_details += ["C_5GHZ" , radio['CH']]
            curr_ap_details += ["P_5GHZ" , radio['TXP']]
            # $redis.hset "AP:#{mc.info['NASID']}", "C_5GHZ" , radio['CHANNEL']
            # $redis.hset "AP:#{mc.info['NASID']}", "P_5GHZ" , radio['TXPOWER']
          end
        end
      end

      if $redis.hget("PCC:GLOBAL:CONFIG", "enable_alerts") == "1" && ap_details['alert'] == "1" && JSON.parse($redis.get('PCC:ORG:ALERT:STATUS') || '[]').include?(ap_details['org_id']) && (mc.info["FIRST_HB"] == 1 || can_run_alert?(mc.info['NASID'],ap_details['alert_last_run_at']))
        #Create Alerts worker
        curr_ap_details += ["alert_last_run_at", Time.now.to_i]
       # jid=AlertsWorker.perform_async(message, mc.created_at.to_i)
        jid = ALERTS_SIDEKIQ.push(
                "class" => "AlertsWorker",
                "args"  => [message, mc.created_at.to_i],
                "queue" => "alerts"
              )

        puts "Heartbeat worker completed --- Alerts Worker #{jid}"
      end

      $redis.hmset("AP:#{mc.info['NASID']}", curr_ap_details) if curr_ap_details.present?
      
      if (firmware_changed || bn_changed) #&& ap_details['hw_type'] != 'switch'
        worker_params = prepare_router_inventory_worker_params(mc, ap_details, firmware_changed, bn_changed)
        p "[HEARTBEAT][#{nasid}] Queuing RouterInventoryUpdateWorker with params: #{worker_params.inspect}"
        RouterInventoryUpdateWorker.perform_async(worker_params) unless worker_params.blank?
      end

      if ap_details['vendor_type'] == '6' #&& ap_details['test_device'] != 'true'
        if (mc.info['CONSUME_ID'] != ap_details['CONSUME_ID']) && ap_details['test_device'] != 'true'
          ri=RouterInventory.where(mac_id: mc.info['NASID']).last
          p "[OPENWIFI][SWITCH][APPLY] Applying latest config for #{mc.info['NASID']}--- #{mc.id}"
          ri.update_redis(true,true,true) if ri.present?
        end

        if ap_details["pending_upgrade"].present? && ap_details["pending_upgrade"].to_i > 0
          pending_upgrade_id = ap_details["pending_upgrade"].to_i
          job_id = ap_details["upgrade_job_id"]
          unless ap_details['ongoing_upgrade'] == "true" && job_id.present?
            PushUpgradeWorker.perform_async(mc.info['NASID'], pending_upgrade_id)
          end
        end
      else
        RouterInventory.where(mac_id: mc.info['NASID']).last.try(:update_redis) if (mc.info["FIRST_HB"] == 1 && config_update)
      end
      
      if (mc.info["FIRST_HB"] == 1 || ap_details['hw_part_no'].blank?) && mc.info["HW_PART_NO"].present? && mc.info["HW_PART_NO"] != ""# && !mc.info["HW_PART_NO"].nil?
        ri = RouterInventory.find_by_mac_id mc.info['NASID']
        ri.set_hw_part_no mc.info["HW_PART_NO"] if ri.present? && ri.hardware_part_id.blank?
      end

      # if mc.info["FIRST_HB"] != 1
      #   UplinkConnectivity.connectivity_record(Thread.current["#{mc.info['NASID']}"], Time.now.utc) if Thread.current["#{mc.info['NASID']}"].present?
      #   Thread.current["#{mc.info["NASID"]}"] = nil
      # end

    end
  end

  def can_run_alert?(device_mac, last_run)
    # Check the last run for alerts
    if last_run.nil? || (Time.now.to_i - last_run.to_i) > 120 # Run every 60 seconds
      p "[ALERTS-RUN][#{device_mac}] Running alerts check"
      return true
    end
    p "[ALERTS-SKIP][#{device_mac}] Running alerts check"
    false
  end
  
  private

  def record_ap_downtime(mac_id, ap_down_time, is_restart)
    ApDowntime.find_or_create_by(mac: mac_id, st: Time.zone.at(ap_down_time['st'].to_i), et: Time.zone.at(ap_down_time['et'].to_i), sec: ap_down_time['sec'], is_restart: is_restart)
  end

  def prepare_router_inventory_worker_params(mc, ap_details, firmware_changed, bn_changed)
    worker_params = {}

    if firmware_changed
      worker_params[:current_firmware] = mc.info["PIAP_VERSION"]
      worker_params[:previous_firmware] = ap_details["version"] if ap_details["version"].present?
    end

    if bn_changed
      worker_params[:build_number] = mc.info["BN"]
    end

    # if ip_changed
    #   if mc.s_info.present? && mc.s_info["PUBLIC_IP"].present?
    #     worker_params[:public_ip] = mc.s_info["PUBLIC_IP"]
    #   end

    #   prev_active_uplink = ap_details['curr_active_uplink']
    #   if current_active_uplink.present? && current_active_uplink != prev_active_uplink
    #     worker_params[:current_active_uplink] = current_active_uplink.to_i
    #   end

    #   p "[HEARTBEAT][#{mc.info['NASID']}] IP changed - adding IP data: public_ip=#{worker_params[:public_ip]}, current_active_uplink=#{worker_params[:current_active_uplink]}"
    # end

    worker_params[:nasid] = mc.info['NASID'] if worker_params.present?

    worker_params
  end
  
end
