class Chargeback
  class Consumption
    def initialize(start_time, end_time)
      @start_time, @end_time = start_time, end_time
    end

    def consumed_hours_in_interval
      # Why we need this?
      #   1) We cannot charge for hours until the resources existed (vm provisioned in the middle of month)
      #   2) We cannot charge for future hours (i.e. weekly report on Monday, should charge just monday)
      #   3) We cannot charge for hours after the resource has been retired.
      @consumed_hours_in_interval ||= begin
                                        consumed = (consumption_end - consumption_start).round / 1.hour
                                        consumed > 0 ? consumed : 0
                                      end
    end

    def hours_in_month
      # If the interval is monthly, we have use exact number of days in interval (i.e. 28, 29, 30, or 31)
      # othewise (for weekly and daily intervals) we assume month equals to 30 days
      monthly? ? hours_in_interval : (30.days / 1.hour)
    end

    def consumption_start
      [@start_time, born_at].compact.max
    end

    def resource_end_of_life
      if resource.try(:retires_on)
        resource.retires_on
      elsif resource.try(:ems_id).nil?
        resource.try(:updated_on)
      end
    end

    def consumption_end
      [Time.current, @end_time, resource_end_of_life].compact.min
    end

    def report_interval_start
      @start_time
    end

    def report_interval_end
      [Time.current, @end_time].min
    end

    def rollup_records_tag_names
      tag_names
    end

    def tag_filter_for_rollup_records(_tag)
    end

    private

    def hours_in_interval
      @hours_in_interval ||= (@end_time - @start_time).round / 1.hour
    end

    def monthly?
      # A heuristic. Is the interval lenght about 30 days?
      (hours_in_interval * 1.hour - 30.days).abs < 3.days
    end

    def born_at
      resource.try(:created_on)
    end
  end
end
