require 'forwardable'

module Chronicle
  module ETL
    # A record of what happened in the running of a job. We're interested in
    # tracking when it ran, if it was successful, and what the latest record
    # we found is (to use as a cursor for the next time)
    class JobLog
      extend Forwardable

      attr_accessor :job,
        :job_id,
        :last_id,
        :highest_timestamp,
        :num_records_processed,
        :started_at,
        :finished_at,
        :success

      def_delegators :@job, :save_log?

      # Create a new JobLog for a given Job
      def initialize
        @num_records_processed = 0
        @success = false
        yield self if block_given?
      end

      # Log the result of a single transformation in a job
      # @param transformer [Chronicle::ETL::Tranformer] The transformer that ran
      def log_transformation(_transformer)
        # @last_id = transformer.id if transformer.id

        # Save the highest timestamp that we've encountered so far
        # @highest_timestamp = [transformer.timestamp, @highest_timestamp].compact.max if transformer.timestamp

        # TODO: a transformer might yield nil. We might also want certain transformers to explode
        # records into multiple new ones. Therefore, this this variable will need more subtle behaviour
        @num_records_processed += 1
      end

      # Indicate that a job has started
      def start
        @started_at = Time.now
      end

      # Indicate that a job has finished
      def finish
        @finished_at = Time.now
        @success = true
      end

      def error
        @finished_at = Time.now
      end

      def job=(job)
        @job = job
        @job_id = job.id
      end

      def duration
        return unless @finished_at && @started_at

        @finished_at - @started_at
      end

      # Take a JobLog's instance variables and turn them into a hash representation
      def serialize
        {
          job_id: @job_id,
          last_id: @last_id,
          highest_timestamp: @highest_timestamp,
          num_records_processed: @num_records_processed,
          started_at: @started_at,
          finished_at: @finished_at,
          success: @success
        }
      end

      # Create a new JobLog and set its instance variables from a serialized hash
      def self.build_from_serialized(attrs)
        attrs.delete(:id)
        new do |job_log|
          attrs.each do |key, value|
            setter = :"#{key}="
            job_log.send(setter, value)
          end
        end
      end
    end
  end
end
