class Api::V1::AccessPointsController < Api::V1::ApiController
  protect_from_forgery with: :null_session
  before_action :user_authentication_for_api
  before_action :check_network_presence?, only: [:provisioning], if: Proc.new { |c| c.request.format.json? }

  api :GET, "/v1/access_points/list_inventory", "List Inventory"  
  # param :access_token, String, :desc => "User Access Token", :required => true
  param :mac_id, String, :desc => "Device Macid"

  def list_inventory
    inventory = params[:mac_id]
    routers_list = @user.organisation.router_inventories.page(params[:page] || 1).per(params[:per_page] || 100)
    router = @user.organisation.router_inventories.where(:mac_id => inventory)
    current, total, per_page = routers_list.current_page, routers_list.total_pages, routers_list.limit_value
    if inventory.present?
      if router.present?
        render json: { data: { devices: router.map{|n| n.json_build} }, status: 200 }
      else
        render json: { msg: "Requested inventory not found check your router inventory", error_code: 1011}, status: 404
      end
    else
      render json: { data: { devices: routers_list.map{|n| n.json_build}, meta: { current: current, previous: (current>1 ? (current-1) : nil), next: (current==total ? nil : (current+1)), per_page: per_page, pages: total, count: routers_list.total_count }}, status: 200 }
    end
  end

  api :POST, "/v1/access_points/provisioning", "AP provisioning"  
  # param :access_token, String, :desc => "User Access Token", :required => true
  param :mac_id, String, :desc => "Device Macid", :required => true
  param :network_id, String, :desc => "Network Id", :required => true

  def provisioning
    if params[:mac_id].present?
      macids = params[:mac_id]
      invalid_mac_ids = []
      unless macids.blank?
        inventory = macids.split(',')
        inventory.each do |router|
          status, message = RouterInventory.validate_router(router,@user.organisation)
          invalid_mac_ids << router if status == false
        end
      end
      # Move to network if device is already present in inventory
      valid_ris = @user.organisation.router_inventories.where(mac_id: invalid_mac_ids, location_network_id: nil)
      invalid_mac_ids -= valid_ris.pluck(:mac_id)
      if valid_ris.present?
        ln = @user.location_networks.where(id: params[:network_id]).last
        if ln.present?
          valid_ris.each do |ri|
            ri.location_network_id = ln.id
            ri.save
          end
        end
      end
      if !invalid_mac_ids.present?
        inventory = macids.split(',')
        ln = @user.location_networks.where(id: params[:network_id]).last
        inventory.each{|router| RouterInventory.router_activation([router,ln.try(:network_name)],@user,false)}
        render json: { msg: "Successfully created new Devices", devices: inventory.map{|router| RouterInventory.where(mac_id: router).last.json_build}, status: 200 }
      elsif @user.organisation.router_inventories.count.to_i >= @user.organisation.no_of_aps.to_i
        render json: { msg: "You have reached the maximum limit #{@user.organisation.no_of_aps} to add inventories", error_code: 1005 }, status: 422 
      else
        render json: { msg: "Following macids #{invalid_mac_ids.join(",")} are invalid or already provisioned. Please check your macids", error_code: 1006 }, status: 422
      end
    else
      render json: { msg: "macids or network name is blank", error_code: 1012 }, status: 422
    end
  end

  api :PUT, "/v1/access_points/apply_configuration", "Apply Configuration"  
  # param :access_token, String, :desc => "User Access Token", :required => true
  param :mac_ids, String, :desc => "Device Macid", :required => true
  param :init_template_name, String, :desc => "Init Template Name"
  param :init_template_id, Integer, :desc => "Init Template Id"
  
  def apply_configuration
    @saved_mac_ids = []
    init_template_name = params[:init_template_name]
    init_template_id = params[:init_template_id]
    if (init_template_name.present? || init_template_id.present?) && (params[:mac_ids].present?)
      macids_params = params[:mac_ids].split(",")
      all_mac_ids = macids_params.map{|n| n.length == 12 ? n.scan(/../).join(":").upcase : n.upcase}
      if init_template_name 
        init_template = @user.organisation.init_templates.where(:name => init_template_name).first
      else
        init_template = @user.organisation.init_templates.where(:id => init_template_id).first
      end
      device_ids = @user.organisation.router_inventories.where(:mac_id => all_mac_ids)
      if init_template.present? && device_ids.present?
        routers = device_ids
        routers.each do |router|
          router.uplinks.update_all(is_deleted: true)
          uplink_details = init_template.details
          uplink_details.each do |uplink_detail|
            if uplink_detail["uplink_type"] == "1"
              router.uplinks.build(uplink_detail)
            elsif uplink_detail["uplink_type"] == "2" || uplink_detail["uplink_type"] == "3"
              router.uplinks.build(uplink_detail) if router.hardware_part.try(:wifi_uplink) == true
            elsif uplink_detail["uplink_type"] == "4"
              router.uplinks.build(uplink_detail) if router.hardware_part.try(:usb) == true
            end
          end
          @saved_mac_ids << router.mac_id if router.save
        end
        @non_saved_ids = all_mac_ids - @saved_mac_ids
        @result = status_message(@non_saved_ids.count,'add_init_template')
      elsif device_ids.blank?
        render json: { msg: "Requested macids are not found. Please check your macids", error_code: 1013 }, status: 404
      else
        render json: { msg: "Requested configuration is not found. Please check your configuration name", error_code: 1014 }, status: 404
      end
    else
      render json: { msg: "Init Template name or macid is not present", error_code: 1015 }, status: 422
    end
  end

  def current_status
    ri = @user.organisation.router_inventories.where(:mac_id => params[:mac_id]).last
    last_hb_data = $redis.hgetall "AP:#{params[:mac_id]}"
    last_seen_time = (last_hb_data["last_hb"].blank? ? nil : last_hb_data["last_hb"].to_i)

    if ri.blank?
      render json: {status: 404, msg: "Requested device is not found. Please check the device MAC.", error_code: 1011}, status: 404
    else
      render :json => {:status => 200, :data => {:name => last_hb_data['AP'], :device_status => (ri.is_up? ? "UP" : "DOWN"), :firmware_version => last_hb_data['version'], :network_name => last_hb_data['Network'], :hardware_model => last_hb_data['HW'], :public_ip => last_hb_data['pub_ip'], :last_seen_time => last_seen_time}}, status: 200
    end
  end

  def status_message count,type
    if count.to_i == 0 && type == 'add_init_template'
      render json: { msg: "Successfully added uplink config to selected devices", status: 200 }
    else
      render json: { msg: "Oops! For the following macids #{@non_saved_ids.join(",")} of devices uplink config are not applied", status: 1016 }, status: 422
    end
  end

  def release_devices
    unless params[:devices].blank?
      released_mac_ids = []
      not_released_mac_ids = []
      routers = @user.organisation.router_inventories.where(:mac_id => params[:devices])
      routers.each do |router|
        router.location_network_id = nil
        if router.save
          released_mac_ids << router.mac_id
        else
          not_released_mac_ids << router.mac_id
        end
      end
      render json: {msg: "Devices not found. Please check the devices."}, status: 422 if routers.blank?
      render json: {msg: "Successfully Released devices from network", success_devices: released_mac_ids, failed_devices: not_released_mac_ids} if released_mac_ids.present? && not_released_mac_ids.blank?
      render json: {msg: "Successfully Released few devices from network. Please check the failed devices for non released devices.", success_devices: released_mac_ids, failed_devices: not_released_mac_ids}, status: 422 if released_mac_ids.present? && not_released_mac_ids.present?
      render json: {msg: "Oops! There was an issue in releasing devices from network. Please check the failed devices.", error_code: 1017, success_devices: released_mac_ids, failed_devices: not_released_mac_ids}, status: 422 if released_mac_ids.blank? && not_released_mac_ids.present?
    else
      render json: { msg: "Please provide atleast one device.", error_code: 1026}, status: 422
    end
  end

  def remove_devices
    unless params[:devices].blank?
      removed_mac = []
      not_removed_mac = []
      routers = @user.organisation.router_inventories.where(:mac_id => params[:devices])
      routers.each do |router|
        if router.destroy
          removed_mac << router.mac_id
        else
          not_removed_mac << router.mac_id
        end
      end
      render json: {msg: "Devices not found. Please check the devices."}, status: 422 if routers.blank?
      render json: {msg: "Successfully removed devices from Inventory", success_devices: removed_mac, failed_devices: not_removed_mac} if removed_mac.present? && not_removed_mac.blank?
      render json: {msg: "Successfully removed few devices from Inventory. Please check the failed devices for non removed devices.", success_devices: removed_mac, failed_devices: not_removed_mac}, status: 422 if removed_mac.present? && not_removed_mac.present?
      render json: {msg: "Oops! There was an issue in removing devices from Inventory. Please check the failed devices.", error_code: 1018, success_devices: removed_mac, failed_devices: not_removed_mac}, status: 422 if removed_mac.blank? && not_removed_mac.present?
    else
      render json: { msg: "Please provide atleast one device.", error_code: 1026}, status: 422
    end
  end

  def move_devices
    unless params[:devices].blank?
      network = @user.organisation.location_networks.find_by_id(params[:existing_network_id])
      if network.blank?
        render json: {msg: "Network is not found. Please check your existing network id", error_code: 1019}, status: 404
      else
        routers = @user.organisation.router_inventories.where(:id => params[:devices]).pluck(:id)
        routers = @user.organisation.router_inventories.where(:mac_id => params[:devices]).pluck(:id) unless routers.present?
        response = @user.organisation.router_inventories.change_network(routers,network,"no")
        if response.blank?
          render json: { msg: "Successfully Moved Devices", devices: routers.map{|router| RouterInventory.find_by_id(router).json_build}}
        else
          failed_devices = @user.organisation.router_inventories.where(:id => response.flatten).pluck(:mac_id)
          success_devices = @user.organisation.router_inventories.where(:id => (routers - response.flatten)).map &:json_build
          render json: { msg: "Oops! there was some problem in Moving Devices", error_code: 1020, devices: success_devices, failed_devices: failed_devices }, status: 422
        end
      end
    else
      render json: { msg: "Please provide atleast one device.", error_code: 1026}, status: 422
    end
  end

  def get_devices_from_serial
    if params[:serial].present?
      serials = params[:serial].split(',').map(&:strip)
      @devices = MasterRouterInventory.where(serial: serials)
      render json: {data: {devices: @devices.map(&:json_build)}}
    else
      render json: { msg: "Serial number is required", error_code: 1027 }, status: 422
    end
  end

end
