# frozen_string_literal: true

module Points
  module RawData
    class Clearer
      BATCH_SIZE = 10_000

      def initialize
        @stats = { cleared: 0, skipped: 0 }
      end

      def call
        Rails.logger.info('Starting raw_data clearing for verified archives...')

        verified_archives.find_each do |archive|
          clear_archive_points(archive)
        end

        Rails.logger.info("Clearing complete: #{@stats}")
        @stats
      end

      def clear_specific_archive(archive_id)
        archive = Points::RawDataArchive.find(archive_id)

        unless archive.verified_at.present?
          Rails.logger.warn("Archive #{archive_id} not verified, skipping clear")
          return { cleared: 0, skipped: 0 }
        end

        clear_archive_points(archive)
      end

      def clear_month(user_id, year, month)
        archives = Points::RawDataArchive.for_month(user_id, year, month)
                                        .where.not(verified_at: nil)

        Rails.logger.info("Clearing #{archives.count} verified archives for #{year}-#{format('%02d', month)}...")

        archives.each { |archive| clear_archive_points(archive) }
      end

      private

      def verified_archives
        # Only archives that are verified but have points with non-empty raw_data
        Points::RawDataArchive
          .where.not(verified_at: nil)
          .where(id: points_needing_clearing.select(:raw_data_archive_id).distinct)
      end

      def points_needing_clearing
        Point.where(raw_data_archived: true)
             .where.not(raw_data: {})
             .where.not(raw_data_archive_id: nil)
      end

      def clear_archive_points(archive)
        Rails.logger.info(
          "Clearing points for archive #{archive.id} " \
          "(#{archive.month_display}, chunk #{archive.chunk_number})..."
        )

        point_ids = Point.where(raw_data_archive_id: archive.id)
                         .where(raw_data_archived: true)
                         .where.not(raw_data: {})
                         .pluck(:id)

        if point_ids.empty?
          Rails.logger.info("No points to clear for archive #{archive.id}")
          return
        end

        cleared_count = clear_points_in_batches(point_ids)
        @stats[:cleared] += cleared_count
        Rails.logger.info("✓ Cleared #{cleared_count} points for archive #{archive.id}")
      rescue StandardError => e
        ExceptionReporter.call(e, "Failed to clear points for archive #{archive.id}")
        Rails.logger.error("✗ Failed to clear archive #{archive.id}: #{e.message}")
      end

      def clear_points_in_batches(point_ids)
        total_cleared = 0

        point_ids.each_slice(BATCH_SIZE) do |batch|
          Point.transaction do
            Point.where(id: batch).update_all(raw_data: {})
            total_cleared += batch.size
          end
        end

        total_cleared
      end
    end
  end
end
