# frozen_string_literal: true

module Visits
  # Coordinates the process of detecting and creating visits from tracked points
  class SmartDetect
    MINIMUM_VISIT_DURATION = 3.minutes
    MAXIMUM_VISIT_GAP = 30.minutes
    MINIMUM_POINTS_FOR_VISIT = 3

    attr_reader :user, :start_at, :end_at, :points

    def initialize(user, start_at:, end_at:)
      @user = user
      @start_at = start_at.to_i
      @end_at = end_at.to_i
      @points = user.points.not_visited
                    .order(timestamp: :asc)
                    .where(timestamp: start_at..end_at)
    end

    def call
      return [] if points.empty?

      potential_visits = Visits::Detector.new(points).detect_potential_visits
      merged_visits    = Visits::Merger.new(points).merge_visits(potential_visits)
      grouped_visits   = group_nearby_visits(merged_visits).flatten

      Visits::Creator.new(user).create_visits(grouped_visits)
    end

    private

    def group_nearby_visits(visits)
      visits.group_by do |visit|
        [
          (visit[:center_lat] * 1000).round / 1000.0,
          (visit[:center_lon] * 1000).round / 1000.0
        ]
      end.values
    end
  end
end
