module Dunlop::WorkflowInstanceModel::StateMachineHandling
  extend ActiveSupport::Concern
  STATE_ORDER = %w[uncategorized unplanned planned overdue active any_rejected all_completed].freeze

  def final_states
    %w[all_completed any_rejected]
  end

  included do
    state_machine initial: :uncategorized do
      after_transition do: :after_transition_hook
      before_transition do: :before_transition_hook
      event(:uncategorized)  { transition any => :uncategorized }
      event(:unplanned)      { transition any => :unplanned }
      event(:planned)        { transition %i[uncategorized unplanned planned overdue any_rejected] => :planned }
      event(:activate)       { transition %i[uncategorized unplanned planned overdue any_rejected all_completed] => :active } # Sub process monitoring
      event(:overdue)        { transition %i[uncategorized unplanned planned active] => :overdue } # Sub process monitoring
      event(:all_completed)  { transition any => :all_completed }
      event(:any_rejected)   { transition any => :any_rejected }
    end

    before_save :set_state_based_on_subprocess_states
  end

  # Gets triggered after a transition
  def after_transition_hook(transition)
  end

  # Gets triggered before a transition
  def before_transition_hook(transition)
  end

  def set_state_based_on_subprocess_states
    states = workflow_steps.compact.map(&:state).compact.uniq
    if states == ['completed']
      self.state = 'all_completed'
    elsif states.include? 'rejected'
      self.state = 'any_rejected'
    elsif states.include? 'overdue'
      self.state = 'overdue'
    elsif (states & %w[processing rejected completed]).any?
      self.state = 'active'
    elsif is_planned?
      self.state = 'planned'
    else
      self.state = 'unplanned'
    end
    true # do not halt propagation
  end

  module ClassMethods
    def sorted_state_count
      group(:state).count.sort_by{|state, count| STATE_ORDER.index(state) || 99 }
    end
  end
end
