# frozen_string_literal: true class Users::ImportData::Areas BATCH_SIZE = 1000 def initialize(user, areas_data) @user = user @areas_data = areas_data end def call return 0 unless areas_data.is_a?(Array) Rails.logger.info "Importing #{areas_data.size} areas for user: #{user.email}" valid_areas = filter_and_prepare_areas if valid_areas.empty? Rails.logger.info "Areas import completed. Created: 0" return 0 end deduplicated_areas = filter_existing_areas(valid_areas) if deduplicated_areas.size < valid_areas.size Rails.logger.debug "Skipped #{valid_areas.size - deduplicated_areas.size} duplicate areas" end total_created = bulk_import_areas(deduplicated_areas) Rails.logger.info "Areas import completed. Created: #{total_created}" total_created end private attr_reader :user, :areas_data def filter_and_prepare_areas valid_areas = [] skipped_count = 0 areas_data.each do |area_data| next unless area_data.is_a?(Hash) unless valid_area_data?(area_data) skipped_count += 1 next end prepared_attributes = prepare_area_attributes(area_data) valid_areas << prepared_attributes if prepared_attributes end if skipped_count > 0 Rails.logger.warn "Skipped #{skipped_count} areas with invalid or missing required data" end valid_areas end def prepare_area_attributes(area_data) attributes = area_data.except('created_at', 'updated_at') attributes['user_id'] = user.id attributes['created_at'] = Time.current attributes['updated_at'] = Time.current attributes['radius'] ||= 100 attributes.symbolize_keys rescue StandardError => e Rails.logger.error "Failed to prepare area attributes: #{e.message}" Rails.logger.error "Area data: #{area_data.inspect}" nil end def filter_existing_areas(areas) return areas if areas.empty? existing_areas_lookup = {} user.areas.select(:name, :latitude, :longitude).each do |area| key = [area.name, area.latitude.to_f, area.longitude.to_f] existing_areas_lookup[key] = true end filtered_areas = areas.reject do |area| key = [area[:name], area[:latitude].to_f, area[:longitude].to_f] if existing_areas_lookup[key] Rails.logger.debug "Area already exists: #{area[:name]}" true else false end end filtered_areas end def bulk_import_areas(areas) total_created = 0 areas.each_slice(BATCH_SIZE) do |batch| begin result = Area.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} areas, created #{batch_created}, total created: #{total_created}" rescue StandardError => e Rails.logger.error "Failed to process area batch: #{e.message}" Rails.logger.error "Batch size: #{batch.size}" Rails.logger.error "Backtrace: #{e.backtrace.first(3).join('\n')}" end end total_created end def valid_area_data?(area_data) return false unless area_data.is_a?(Hash) return false unless area_data['name'].present? return false unless area_data['latitude'].present? return false unless area_data['longitude'].present? true rescue StandardError => e Rails.logger.debug "Area validation failed: #{e.message} for data: #{area_data.inspect}" false end end