module Ahoy
  module QueryMethods
    extend ActiveSupport::Concern

    module ClassMethods
      def where_event(name, properties = {})
        where(name: name).where_props(properties)
      end

      def where_props(properties)
        return all if properties.empty?

        adapter_name = respond_to?(:connection_db_config) ? connection_db_config.adapter.to_s : "mongoid"
        case adapter_name
        when "mongoid"
          where(properties.to_h { |k, v| ["properties.#{k}", v] })
        when /mysql|trilogy/i
          where("JSON_CONTAINS(properties, ?, '$') = 1", properties.to_json)
        when /postg/i
          case columns_hash["properties"].type
          when :hstore
            properties.inject(all) do |relation, (k, v)|
              if v.nil?
                relation.where("properties -> ? IS NULL", k.to_s)
              else
                relation.where("properties -> ? = ?", k.to_s, v.to_s)
              end
            end
          when :jsonb
            where("properties @> ?", properties.to_json)
          else
            where("properties::jsonb @> ?", properties.to_json)
          end
        when /sqlite/i
          properties.inject(all) do |relation, (k, v)|
            if v.nil?
              relation.where("JSON_EXTRACT(properties, ?) IS NULL", "$.#{k}")
            else
              relation.where("JSON_EXTRACT(properties, ?) = ?", "$.#{k}", v.as_json)
            end
          end
        else
          raise "Adapter not supported: #{adapter_name}"
        end
      end
      alias_method :where_properties, :where_props

      def group_prop(*props)
        # like with group
        props.flatten!

        relation = all
        adapter_name = respond_to?(:connection_db_config) ? connection_db_config.adapter.to_s : "mongoid"
        case adapter_name
        when "mongoid"
          raise "Adapter not supported: #{adapter_name}"
        when /mysql|trilogy/i
          props.each do |prop|
            quoted_prop = connection_pool.with_connection { |c| c.quote("$.#{prop}") }
            relation = relation.group("JSON_UNQUOTE(JSON_EXTRACT(properties, #{quoted_prop}))")
          end
        when /postg/i
          # convert to jsonb to fix
          # could not identify an equality operator for type json
          # and for text columns
          column_type = columns_hash["properties"].type
          cast = [:jsonb, :hstore].include?(column_type) ? "" : "::jsonb"

          props.each do |prop|
            quoted_prop = connection_pool.with_connection { |c| c.quote(prop) }
            relation = relation.group("properties#{cast} -> #{quoted_prop}")
          end
        when /sqlite/i
          props.each do |prop|
            quoted_prop = connection_pool.with_connection { |c| c.quote("$.#{prop}") }
            relation = relation.group("JSON_EXTRACT(properties, #{quoted_prop})")
          end
        else
          raise "Adapter not supported: #{adapter_name}"
        end
        relation
      end
    end
  end
end

# backward compatibility
Ahoy::Properties = Ahoy::QueryMethods
