module Panel
  #
  class StatisticsController < PanelController
    skip_load_resource
    skip_authorize_resource
    #before_action :init_form

    def details
      search_expedients(params)
      @expedients = @expedients.reorder("expedients.id ASC").includes(:events)

      respond_to do |format|
        format.html
        format.xlsx { render layout: false }
      end
    end

    def index
      search_expedients(params)
      init_form

      respond_to do |format|
        format.html
        format.xlsx { render layout: false }
      end

    end

    def export
      search_expedients(params)
    end

    def cities
      @state = State.find(params[:id])
      @cities = {}

      @state.cities.each do |c|
        @cities[c.id] = c.name
      end

      respond_to do |format|
        format.json { render json: @cities }
      end
    end

    def tags
      @institution = Institution.accessible_by(current_ability).find(params[:id])
      @filter_tags = {}
      @tags        = Expedient.tag_counts_custom(Expedient.by_institution(@institution.id).accessible_by(current_ability).ids).pluck(:name, :name)

      @filter_tags = @tags.sort{|a,z|a[1]<=>z[1]}

      respond_to do |format|
        format.json { render json: @filter_tags }
      end
    end

    def scategories
      @institution = Institution.accessible_by(current_ability).find(params[:id])
      @kind        = params[:k]
      @filter_scategories = {}
      @scategories = ManagementCategory.accessible_by(current_ability).where(institution_id: @institution.id, kind: @kind)

      @scategories.each do |sc|
        @filter_scategories[sc.id] = sc.name
      end

      @filter_scategories = @filter_scategories.sort{|a,z|a[1]<=>z[1]}.to_h

      respond_to do |format|
        format.json { render json: @filter_scategories }
      end
    end

    def entryways
      @institution = Institution.accessible_by(current_ability).find(params[:id])
      @filter_entry_ways = {}
      @entry_ways  = EntryWay.accessible_by(current_ability).where(institution_id: @institution.id).or(EntryWay.where(institution_id: nil)).order(:name)

      @entry_ways.each do |ew|
        @filter_entry_ways[ew.id] = ew.name
      end

      @filter_entry_ways = @filter_entry_ways.sort{|a,z|a[1]<=>z[1]}.to_h

      respond_to do |format|
        format.json { render json: @filter_entry_ways }
      end
    end

    def managementsassigned
      @institution = Institution.accessible_by(current_ability).find(params[:id])
      @filter_managements_assigned = {}
      @managements_assigned = User.by_institution(@institution.id).accessible_by(current_ability).order(:name)

      @managements_assigned.each do |ma|
        @filter_managements_assigned[ma.id] = ma.name
      end

      @filter_managements_assigned = @filter_managements_assigned.sort{|a,z|a[1]<=>z[1]}.to_h

      respond_to do |format|
        format.json { render json: @filter_managements_assigned }
      end
    end

    def administrativearea
      @institution = Institution.accessible_by(current_ability).find(params[:id])
      @filter_administrative_area = {}
      @managements_assigned = User.by_institution(@institution.id).accessible_by(current_ability).order(:name)

      @managements_assigned.map(&:administrative_area).uniq.each do |ma|
        unless ma == ""
          @filter_administrative_area[ma] = ma
        end
      end

      @filter_administrative_area = (@filter_administrative_area.sort{|a,z|a[1]<=>z[1]} - [""]).to_h
      respond_to do |format|
        format.json { render json: @filter_administrative_area }
      end
    end

    def branches
      @institution = Institution.accessible_by(current_ability).find(params[:id])
      @filter_branches = {}
      @branches = Branch.by_institution(@institution.id).accessible_by(current_ability)

      @branches.each do |b|
        @filter_branches[b.id] = b.name
      end

      @filter_branches = @filter_branches.sort{|a,z|a[1]<=>z[1]}.to_h unless @branches.empty?

      respond_to do |format|
        format.json { render json: @filter_branches }
      end
    end

    def init_form
      @filter_managements          = @managements
      @filter_categories           = ManagementCategory.accessible_by(current_ability)
      @filter_entry_ways           = EntryWay.where(institution_id: nil).order(:name)
      @filter_states               = State.all
      @filter_genders              = {Femenino: "f", Masculino: "m"}
      @filter_contact_time         = [{id: 0, name: "Todos los casos"},
                                      {id: 1, name: "Más de 48 horas"},
                                      {id: 2, name: "Menos de 48 horas"},
                                      {id: 3, name: "Sin contacto"},
                                      {id: 4, name: "Contacto fallido"},
                                      {id: 5, name: "Anonimos"}]
      @month_begin                 = Date.today.at_beginning_of_month
      @month_end                   = Date.today.at_end_of_month

      if params[:q].present? && params[:q][:institution_id_eq].present? && !params[:q][:institution_id_eq].blank?
        @filter_scategories = {}
      else
        @filter_scategories = {}
      end

      if params[:q].present? && params[:q][:institution_id_eq].present? && !params[:q][:institution_id_eq].blank?
        @institution                 = Institution.find(params[:q][:institution_id_eq])
        @filter_managements_assigned = User.by_institution(@institution.id).accessible_by(current_ability).order(:name)
        @filter_branches             = Branch.by_institution(@institution.id).accessible_by(current_ability)
        @filter_administrative_area  = ((User.by_institution(@institution.id).accessible_by(current_ability).map(&:administrative_area).uniq.sort) - [""])
        @filter_tags                 = Expedient.tag_counts_custom(Expedient.by_institution(@institution.id).accessible_by(current_ability).ids).pluck(:name, :name).sort
      else
        @filter_managements_assigned = {}
        @filter_branches             = {}
        @filter_administrative_area  = {}
        @filter_tags                 = Expedient.tag_counts_custom(Expedient.accessible_by(current_ability).ids).pluck(:name, :name).sort
      end

      if params[:q].present? && params[:q][:state_id_eq].present? && !params[:q][:state_id_eq].blank?
        @state = State.find(params[:q][:state_id_eq])
        @filter_cities = @state.cities
      else
        @filter_cities = {}
      end

      if current_user.has_role?("admin")
        @institutions = Institution.order(:name).select(:id, :name)
      else
        @institutions = Institution.where("id IN (?)", current_user.institution_ids)
      end

    end

    def count_by_state(expedients, state)
      r = 0
      expedients.map(&:state).each{|v| (v == state ? r+=1 : nil)}
      r
    end
    helper_method :count_by_state

    def graph_by_state(expedients)
      expedients.inject(Hash.new(0)) { |total, e| total[Expedient::STATE[e]] += 1 ;total}
    end
    helper_method :graph_by_state

    def count_by_kind(managements, kind)
      r = 0
      managements.map(&:kind).each{|v| (v == kind ? r+=1 : nil)}
      r
    end
    helper_method :count_by_kind

    def graph_by_kind(managements, expedient_ids)
      a = managements.where(expedient_id: expedient_ids)
      a.map(&:kind).inject(Hash.new(0)) { |total, e| total[Management::KIND[e]] += 1 ; total}
    end
    helper_method :graph_by_kind

    def graph_contact_time(expedients)

      expedients = expedients.is_a?(Array) ? Expedient.where(id: expedients.map(&:id)) : expedients

      _e_nil_ids = []
      _anon_ids  = []
      _less      = 0
      _more      = 0
      _wo        = 0
      _fail      = 0
      _anon      = 0

      _e_nil_ids = expedients.by_ct_nil.ids.uniq
      _less      = expedients.by_ct_less.ids.uniq.length
      _more      = expedients.by_ct_more.ids.uniq.length
      _anon      = expedients.by_anon(1).ids.uniq

      _fail_e   = @expedients.by_ct_failed
      _fail_ids = _fail_e.map(&:id).uniq
      _fail     = _fail_ids.length
      _wo       = (_e_nil_ids - (_fail_ids + _anon).uniq).length

      [ ["Menos de 48 horas", _less], ["Más de 48 horas", _more],
        ["Contacto fallido", _fail], ["Sin contacto", _wo], ["Anonimos", _anon.length] ]
    end
    helper_method :graph_contact_time

    def graph_by_entry_way(expedients)
      expedients.map(&:entry_way_id).inject(Hash.new(0)) { |total, e| total[@ew[e]] += 1 ; total}
    end
    helper_method :graph_by_entry_way

    def graph_by_management_category(managements)
      managements.map(&:management_category_id).inject(Hash.new(0)) { |total, e| total[@mc[e]] += 1 ; total}.sort {|a,b| b[1] <=> a[1]}.take(5)
    end
    helper_method :graph_by_management_category

    def graph_by_tags(expedients)
      if expedients.is_a?(Array)
        tags = Expedient.tag_counts_custom(expedients.map(&:id)).pluck(:name, :taggings_count)
      else
        tags = Expedient.tag_counts_custom(expedients.ids).pluck(:name, :taggings_count)
      end
      tags = tags.sort_by{|t| -t[1]}.take(10)
    end
    helper_method :graph_by_tags

    def count_by_expedient_id(managements, expedient_ids, kind)
      r = 0
      managements.map.each{|m| ((expedient_ids.include? m.expedient_id and m.kind == kind)  ? r+=1 : nil)}
      r
    end
    helper_method :count_by_expedient_id

    def check_empty_zero_array(a)
      if a == {}
      else
        c = 0
        a.each{|v| v[1] == 0 ? c += 1 : nil}
        r = (c == a.length ? false : true)
      end
      r
    end
    helper_method :check_empty_zero_array

    def count_by_expedients(managements, expedients)
      r = 0
      managements.map(&:expedient_id).map.each{|m| (expedients.uniq.include?(m) ? (r+=1) : nil)}
      r
    end
    helper_method :count_by_expedients

    def fix_params(fields)
      @p = params.deep_dup
      if @p[:q].present?
        fields.each do |field|
          @p[:q][field[0].to_sym] = field[1]
        end
      else
        @p = {}
        @p[:q] = fields
      end
      @p[:q]
    end
    helper_method :fix_params

    private
      def search_expedients(params)
        modify_params(params)
        @q = Expedient.accessible_by(current_ability).ransack(params[:q])
        @expedients = @q.result.distinct.includes(:institution, :branch, :managements, :entry_way, :user, :events, :tags)

        if params[:q].present?
          params[:qq] = ActionController::Parameters.new({
            kind_eq: params[:q][:managements_kind_eq],
            assigned_ids_cont: params[:q][:managements_assigned_ids_cont]
          })
        end

        @qq = Management.where(expedient_id: @expedients.ids).ransack(params[:qq])
        @managements = @qq.result

        ewids = @expedients.map(&:entry_way_id).uniq
        @ew   = EntryWay.where(id: ewids).inject(Hash.new(0)) {|ew, e| ew[e.id] = e.name ; ew}

        mcids = @managements.map(&:management_category_id).uniq
        @mc   = ManagementCategory.where(id: mcids).inject(Hash.new(0)) {|mc, m| mc[m.id] = m.full_name ; mc}

        @colors = ["3366CC", "DC3912", "FF9900", "109618", "990099", "3B3EAC",
                   "0099C6", "DD4477", "66AA00", "B82E2E", "316395", "994499",
                   "22AA99", "AAAA11", "6633CC", "E67300", "8B0707", "329262",
                   "5574A6", "651067"]

        @_by_institutions       = graph_by_state(@expedients.map(&:state))
        @_by_kind               = graph_by_kind(@managements, @expedients.map(&:id))
        @_contact_time          = graph_contact_time(@expedients)
        @_by_entry_way          = graph_by_entry_way(@expedients)
        @by_management_category = graph_by_management_category(@managements)
        @by_tags                = graph_by_tags(@expedients)
      end

      def modify_params params
        if params[:contact_time].present?
          case params[:contact_time]
          when 0
            #all
          when "1"
            #+48
            params[:q][:by_ct_more] = "1"
          when "2"
            #-48
            params[:q][:by_ct_less] = "1"
          when "3"
            #wo
            params[:q][:by_ct_nil] = "1"
          when "4"
            #failed
            params[:q][:by_ct_failed] = "1"
          when "5"
            #anon
            params[:q][:by_anon] = "1"
          end
        end
      end

      def params_search
        params.permit(:k, :page, :count, :utf8, q: [:institution_id_eq, :branch_id_eq,
          :created_at_gteq, :created__at_lteq, :button, :entry_way_id_eq, :by_aa,
          :managements_assigned_ids_cont, :managements_kind_eq, :state_eq, :city_id_eq,
          :management_category_id, :classification_type_eq, :user_administrative_area_eq,
          :state_id_eq, :city_id_eq, :contact_time, :by_ct_more, :by_ct_less, :by_ct_nil,
          :by_ct_failed, :by_anon, :classification_type_not_eq, :state_not_eq]).permit!
      end
  end
end
