# frozen_string_literal: true

class Users::ImportData::Stats
  BATCH_SIZE = 1000

  def initialize(user, stats_data)
    @user = user
    @stats_data = stats_data
  end

  def call
    return 0 unless stats_data.is_a?(Array)

    Rails.logger.info "Importing #{stats_data.size} stats for user: #{user.email}"

    valid_stats = filter_and_prepare_stats

    if valid_stats.empty?
      Rails.logger.info "Stats import completed. Created: 0"
      return 0
    end

    deduplicated_stats = filter_existing_stats(valid_stats)

    if deduplicated_stats.size < valid_stats.size
      Rails.logger.debug "Skipped #{valid_stats.size - deduplicated_stats.size} duplicate stats"
    end

    total_created = bulk_import_stats(deduplicated_stats)

    Rails.logger.info "Stats import completed. Created: #{total_created}"
    total_created
  end

  private

  attr_reader :user, :stats_data

  def filter_and_prepare_stats
    valid_stats = []
    skipped_count = 0

    stats_data.each do |stat_data|
      next unless stat_data.is_a?(Hash)

      unless valid_stat_data?(stat_data)
        skipped_count += 1
        next
      end

      prepared_attributes = prepare_stat_attributes(stat_data)
      valid_stats << prepared_attributes if prepared_attributes
    end

    if skipped_count > 0
      Rails.logger.warn "Skipped #{skipped_count} stats with invalid or missing required data"
    end

    valid_stats
  end

  def prepare_stat_attributes(stat_data)
    attributes = stat_data.except('created_at', 'updated_at', 'sharing_uuid')

    attributes['user_id'] = user.id
    attributes['created_at'] = Time.current
    attributes['updated_at'] = Time.current
    attributes['sharing_uuid'] = SecureRandom.uuid

    attributes.symbolize_keys
  rescue StandardError => e
    ExceptionReporter.call(e, 'Failed to prepare stat attributes')

    nil
  end

  def filter_existing_stats(stats)
    return stats if stats.empty?

    existing_stats_lookup = {}
    user.stats.select(:year, :month).each do |stat|
      key = [stat.year, stat.month]
      existing_stats_lookup[key] = true
    end

    filtered_stats = stats.reject do |stat|
      key = [stat[:year], stat[:month]]
      if existing_stats_lookup[key]
        Rails.logger.debug "Stat already exists: #{stat[:year]}-#{stat[:month]}"
        true
      else
        false
      end
    end

    filtered_stats
  end

  def bulk_import_stats(stats)
    total_created = 0

    stats.each_slice(BATCH_SIZE) do |batch|
      begin
        result = Stat.upsert_all(
          batch,
          returning: %w[id],
          on_duplicate: :skip
        )

        batch_created = result.count
        total_created += batch_created

        Rails.logger.debug "Processed batch of #{batch.size} stats, created #{batch_created}, total created: #{total_created}"

      rescue StandardError => e
        ExceptionReporter.call(e, 'Failed to process stat batch')
      end
    end

    total_created
  end

  def valid_stat_data?(stat_data)
    return false unless stat_data.is_a?(Hash)

    unless stat_data['year'].present?
      Rails.logger.error "Failed to create stat: Validation failed: Year can't be blank"
      return false
    end

    unless stat_data['month'].present?
      Rails.logger.error "Failed to create stat: Validation failed: Month can't be blank"
      return false
    end

    unless stat_data['distance'].present?
      Rails.logger.error "Failed to create stat: Validation failed: Distance can't be blank"
      return false
    end

    true
  rescue StandardError => e
    Rails.logger.debug "Stat validation failed: #{e.message} for data: #{stat_data.inspect}"
    false
  end
end
